1 //===-- ARMISelDAGToDAG.cpp - A dag to dag inst selector for ARM ----------===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 // 9 // This file defines an instruction selector for the ARM target. 10 // 11 //===----------------------------------------------------------------------===// 12 13 #include "ARM.h" 14 #include "ARMBaseInstrInfo.h" 15 #include "ARMTargetMachine.h" 16 #include "MCTargetDesc/ARMAddressingModes.h" 17 #include "Utils/ARMBaseInfo.h" 18 #include "llvm/ADT/APSInt.h" 19 #include "llvm/ADT/StringSwitch.h" 20 #include "llvm/CodeGen/MachineFrameInfo.h" 21 #include "llvm/CodeGen/MachineFunction.h" 22 #include "llvm/CodeGen/MachineInstrBuilder.h" 23 #include "llvm/CodeGen/MachineRegisterInfo.h" 24 #include "llvm/CodeGen/SelectionDAG.h" 25 #include "llvm/CodeGen/SelectionDAGISel.h" 26 #include "llvm/CodeGen/TargetLowering.h" 27 #include "llvm/IR/CallingConv.h" 28 #include "llvm/IR/Constants.h" 29 #include "llvm/IR/DerivedTypes.h" 30 #include "llvm/IR/Function.h" 31 #include "llvm/IR/Intrinsics.h" 32 #include "llvm/IR/IntrinsicsARM.h" 33 #include "llvm/IR/LLVMContext.h" 34 #include "llvm/Support/CommandLine.h" 35 #include "llvm/Support/Debug.h" 36 #include "llvm/Support/ErrorHandling.h" 37 #include "llvm/Target/TargetOptions.h" 38 39 using namespace llvm; 40 41 #define DEBUG_TYPE "arm-isel" 42 43 static cl::opt<bool> 44 DisableShifterOp("disable-shifter-op", cl::Hidden, 45 cl::desc("Disable isel of shifter-op"), 46 cl::init(false)); 47 48 //===--------------------------------------------------------------------===// 49 /// ARMDAGToDAGISel - ARM specific code to select ARM machine 50 /// instructions for SelectionDAG operations. 51 /// 52 namespace { 53 54 class ARMDAGToDAGISel : public SelectionDAGISel { 55 /// Subtarget - Keep a pointer to the ARMSubtarget around so that we can 56 /// make the right decision when generating code for different targets. 57 const ARMSubtarget *Subtarget; 58 59 public: 60 explicit ARMDAGToDAGISel(ARMBaseTargetMachine &tm, CodeGenOpt::Level OptLevel) 61 : SelectionDAGISel(tm, OptLevel) {} 62 63 bool runOnMachineFunction(MachineFunction &MF) override { 64 // Reset the subtarget each time through. 65 Subtarget = &MF.getSubtarget<ARMSubtarget>(); 66 SelectionDAGISel::runOnMachineFunction(MF); 67 return true; 68 } 69 70 StringRef getPassName() const override { return "ARM Instruction Selection"; } 71 72 void PreprocessISelDAG() override; 73 74 /// getI32Imm - Return a target constant of type i32 with the specified 75 /// value. 76 inline SDValue getI32Imm(unsigned Imm, const SDLoc &dl) { 77 return CurDAG->getTargetConstant(Imm, dl, MVT::i32); 78 } 79 80 void Select(SDNode *N) override; 81 82 bool hasNoVMLxHazardUse(SDNode *N) const; 83 bool isShifterOpProfitable(const SDValue &Shift, 84 ARM_AM::ShiftOpc ShOpcVal, unsigned ShAmt); 85 bool SelectRegShifterOperand(SDValue N, SDValue &A, 86 SDValue &B, SDValue &C, 87 bool CheckProfitability = true); 88 bool SelectImmShifterOperand(SDValue N, SDValue &A, 89 SDValue &B, bool CheckProfitability = true); 90 bool SelectShiftRegShifterOperand(SDValue N, SDValue &A, SDValue &B, 91 SDValue &C) { 92 // Don't apply the profitability check 93 return SelectRegShifterOperand(N, A, B, C, false); 94 } 95 bool SelectShiftImmShifterOperand(SDValue N, SDValue &A, SDValue &B) { 96 // Don't apply the profitability check 97 return SelectImmShifterOperand(N, A, B, false); 98 } 99 bool SelectShiftImmShifterOperandOneUse(SDValue N, SDValue &A, SDValue &B) { 100 if (!N.hasOneUse()) 101 return false; 102 return SelectImmShifterOperand(N, A, B, false); 103 } 104 105 bool SelectAddLikeOr(SDNode *Parent, SDValue N, SDValue &Out); 106 107 bool SelectAddrModeImm12(SDValue N, SDValue &Base, SDValue &OffImm); 108 bool SelectLdStSOReg(SDValue N, SDValue &Base, SDValue &Offset, SDValue &Opc); 109 110 bool SelectCMOVPred(SDValue N, SDValue &Pred, SDValue &Reg) { 111 const ConstantSDNode *CN = cast<ConstantSDNode>(N); 112 Pred = CurDAG->getTargetConstant(CN->getZExtValue(), SDLoc(N), MVT::i32); 113 Reg = CurDAG->getRegister(ARM::CPSR, MVT::i32); 114 return true; 115 } 116 117 bool SelectAddrMode2OffsetReg(SDNode *Op, SDValue N, 118 SDValue &Offset, SDValue &Opc); 119 bool SelectAddrMode2OffsetImm(SDNode *Op, SDValue N, 120 SDValue &Offset, SDValue &Opc); 121 bool SelectAddrMode2OffsetImmPre(SDNode *Op, SDValue N, 122 SDValue &Offset, SDValue &Opc); 123 bool SelectAddrOffsetNone(SDValue N, SDValue &Base); 124 bool SelectAddrMode3(SDValue N, SDValue &Base, 125 SDValue &Offset, SDValue &Opc); 126 bool SelectAddrMode3Offset(SDNode *Op, SDValue N, 127 SDValue &Offset, SDValue &Opc); 128 bool IsAddressingMode5(SDValue N, SDValue &Base, SDValue &Offset, bool FP16); 129 bool SelectAddrMode5(SDValue N, SDValue &Base, SDValue &Offset); 130 bool SelectAddrMode5FP16(SDValue N, SDValue &Base, SDValue &Offset); 131 bool SelectAddrMode6(SDNode *Parent, SDValue N, SDValue &Addr,SDValue &Align); 132 bool SelectAddrMode6Offset(SDNode *Op, SDValue N, SDValue &Offset); 133 134 bool SelectAddrModePC(SDValue N, SDValue &Offset, SDValue &Label); 135 136 // Thumb Addressing Modes: 137 bool SelectThumbAddrModeRR(SDValue N, SDValue &Base, SDValue &Offset); 138 bool SelectThumbAddrModeRRSext(SDValue N, SDValue &Base, SDValue &Offset); 139 bool SelectThumbAddrModeImm5S(SDValue N, unsigned Scale, SDValue &Base, 140 SDValue &OffImm); 141 bool SelectThumbAddrModeImm5S1(SDValue N, SDValue &Base, 142 SDValue &OffImm); 143 bool SelectThumbAddrModeImm5S2(SDValue N, SDValue &Base, 144 SDValue &OffImm); 145 bool SelectThumbAddrModeImm5S4(SDValue N, SDValue &Base, 146 SDValue &OffImm); 147 bool SelectThumbAddrModeSP(SDValue N, SDValue &Base, SDValue &OffImm); 148 template <unsigned Shift> 149 bool SelectTAddrModeImm7(SDValue N, SDValue &Base, SDValue &OffImm); 150 151 // Thumb 2 Addressing Modes: 152 bool SelectT2AddrModeImm12(SDValue N, SDValue &Base, SDValue &OffImm); 153 template <unsigned Shift> 154 bool SelectT2AddrModeImm8(SDValue N, SDValue &Base, SDValue &OffImm); 155 bool SelectT2AddrModeImm8(SDValue N, SDValue &Base, 156 SDValue &OffImm); 157 bool SelectT2AddrModeImm8Offset(SDNode *Op, SDValue N, 158 SDValue &OffImm); 159 template <unsigned Shift> 160 bool SelectT2AddrModeImm7Offset(SDNode *Op, SDValue N, SDValue &OffImm); 161 bool SelectT2AddrModeImm7Offset(SDNode *Op, SDValue N, SDValue &OffImm, 162 unsigned Shift); 163 template <unsigned Shift> 164 bool SelectT2AddrModeImm7(SDValue N, SDValue &Base, SDValue &OffImm); 165 bool SelectT2AddrModeSoReg(SDValue N, SDValue &Base, 166 SDValue &OffReg, SDValue &ShImm); 167 bool SelectT2AddrModeExclusive(SDValue N, SDValue &Base, SDValue &OffImm); 168 169 template<int Min, int Max> 170 bool SelectImmediateInRange(SDValue N, SDValue &OffImm); 171 172 inline bool is_so_imm(unsigned Imm) const { 173 return ARM_AM::getSOImmVal(Imm) != -1; 174 } 175 176 inline bool is_so_imm_not(unsigned Imm) const { 177 return ARM_AM::getSOImmVal(~Imm) != -1; 178 } 179 180 inline bool is_t2_so_imm(unsigned Imm) const { 181 return ARM_AM::getT2SOImmVal(Imm) != -1; 182 } 183 184 inline bool is_t2_so_imm_not(unsigned Imm) const { 185 return ARM_AM::getT2SOImmVal(~Imm) != -1; 186 } 187 188 // Include the pieces autogenerated from the target description. 189 #include "ARMGenDAGISel.inc" 190 191 private: 192 void transferMemOperands(SDNode *Src, SDNode *Dst); 193 194 /// Indexed (pre/post inc/dec) load matching code for ARM. 195 bool tryARMIndexedLoad(SDNode *N); 196 bool tryT1IndexedLoad(SDNode *N); 197 bool tryT2IndexedLoad(SDNode *N); 198 bool tryMVEIndexedLoad(SDNode *N); 199 bool tryFMULFixed(SDNode *N, SDLoc dl); 200 201 /// SelectVLD - Select NEON load intrinsics. NumVecs should be 202 /// 1, 2, 3 or 4. The opcode arrays specify the instructions used for 203 /// loads of D registers and even subregs and odd subregs of Q registers. 204 /// For NumVecs <= 2, QOpcodes1 is not used. 205 void SelectVLD(SDNode *N, bool isUpdating, unsigned NumVecs, 206 const uint16_t *DOpcodes, const uint16_t *QOpcodes0, 207 const uint16_t *QOpcodes1); 208 209 /// SelectVST - Select NEON store intrinsics. NumVecs should 210 /// be 1, 2, 3 or 4. The opcode arrays specify the instructions used for 211 /// stores of D registers and even subregs and odd subregs of Q registers. 212 /// For NumVecs <= 2, QOpcodes1 is not used. 213 void SelectVST(SDNode *N, bool isUpdating, unsigned NumVecs, 214 const uint16_t *DOpcodes, const uint16_t *QOpcodes0, 215 const uint16_t *QOpcodes1); 216 217 /// SelectVLDSTLane - Select NEON load/store lane intrinsics. NumVecs should 218 /// be 2, 3 or 4. The opcode arrays specify the instructions used for 219 /// load/store of D registers and Q registers. 220 void SelectVLDSTLane(SDNode *N, bool IsLoad, bool isUpdating, 221 unsigned NumVecs, const uint16_t *DOpcodes, 222 const uint16_t *QOpcodes); 223 224 /// Helper functions for setting up clusters of MVE predication operands. 225 template <typename SDValueVector> 226 void AddMVEPredicateToOps(SDValueVector &Ops, SDLoc Loc, 227 SDValue PredicateMask); 228 template <typename SDValueVector> 229 void AddMVEPredicateToOps(SDValueVector &Ops, SDLoc Loc, 230 SDValue PredicateMask, SDValue Inactive); 231 232 template <typename SDValueVector> 233 void AddEmptyMVEPredicateToOps(SDValueVector &Ops, SDLoc Loc); 234 template <typename SDValueVector> 235 void AddEmptyMVEPredicateToOps(SDValueVector &Ops, SDLoc Loc, EVT InactiveTy); 236 237 /// SelectMVE_WB - Select MVE writeback load/store intrinsics. 238 void SelectMVE_WB(SDNode *N, const uint16_t *Opcodes, bool Predicated); 239 240 /// SelectMVE_LongShift - Select MVE 64-bit scalar shift intrinsics. 241 void SelectMVE_LongShift(SDNode *N, uint16_t Opcode, bool Immediate, 242 bool HasSaturationOperand); 243 244 /// SelectMVE_VADCSBC - Select MVE vector add/sub-with-carry intrinsics. 245 void SelectMVE_VADCSBC(SDNode *N, uint16_t OpcodeWithCarry, 246 uint16_t OpcodeWithNoCarry, bool Add, bool Predicated); 247 248 /// SelectMVE_VSHLC - Select MVE intrinsics for a shift that carries between 249 /// vector lanes. 250 void SelectMVE_VSHLC(SDNode *N, bool Predicated); 251 252 /// Select long MVE vector reductions with two vector operands 253 /// Stride is the number of vector element widths the instruction can operate 254 /// on: 255 /// 2 for long non-rounding variants, vml{a,s}ldav[a][x]: [i16, i32] 256 /// 1 for long rounding variants: vrml{a,s}ldavh[a][x]: [i32] 257 /// Stride is used when addressing the OpcodesS array which contains multiple 258 /// opcodes for each element width. 259 /// TySize is the index into the list of element types listed above 260 void SelectBaseMVE_VMLLDAV(SDNode *N, bool Predicated, 261 const uint16_t *OpcodesS, const uint16_t *OpcodesU, 262 size_t Stride, size_t TySize); 263 264 /// Select a 64-bit MVE vector reduction with two vector operands 265 /// arm_mve_vmlldava_[predicated] 266 void SelectMVE_VMLLDAV(SDNode *N, bool Predicated, const uint16_t *OpcodesS, 267 const uint16_t *OpcodesU); 268 /// Select a 72-bit MVE vector rounding reduction with two vector operands 269 /// int_arm_mve_vrmlldavha[_predicated] 270 void SelectMVE_VRMLLDAVH(SDNode *N, bool Predicated, const uint16_t *OpcodesS, 271 const uint16_t *OpcodesU); 272 273 /// SelectMVE_VLD - Select MVE interleaving load intrinsics. NumVecs 274 /// should be 2 or 4. The opcode array specifies the instructions 275 /// used for 8, 16 and 32-bit lane sizes respectively, and each 276 /// pointer points to a set of NumVecs sub-opcodes used for the 277 /// different stages (e.g. VLD20 versus VLD21) of each load family. 278 void SelectMVE_VLD(SDNode *N, unsigned NumVecs, 279 const uint16_t *const *Opcodes, bool HasWriteback); 280 281 /// SelectMVE_VxDUP - Select MVE incrementing-dup instructions. Opcodes is an 282 /// array of 3 elements for the 8, 16 and 32-bit lane sizes. 283 void SelectMVE_VxDUP(SDNode *N, const uint16_t *Opcodes, 284 bool Wrapping, bool Predicated); 285 286 /// Select SelectCDE_CXxD - Select CDE dual-GPR instruction (one of CX1D, 287 /// CX1DA, CX2D, CX2DA, CX3, CX3DA). 288 /// \arg \c NumExtraOps number of extra operands besides the coprocossor, 289 /// the accumulator and the immediate operand, i.e. 0 290 /// for CX1*, 1 for CX2*, 2 for CX3* 291 /// \arg \c HasAccum whether the instruction has an accumulator operand 292 void SelectCDE_CXxD(SDNode *N, uint16_t Opcode, size_t NumExtraOps, 293 bool HasAccum); 294 295 /// SelectVLDDup - Select NEON load-duplicate intrinsics. NumVecs 296 /// should be 1, 2, 3 or 4. The opcode array specifies the instructions used 297 /// for loading D registers. 298 void SelectVLDDup(SDNode *N, bool IsIntrinsic, bool isUpdating, 299 unsigned NumVecs, const uint16_t *DOpcodes, 300 const uint16_t *QOpcodes0 = nullptr, 301 const uint16_t *QOpcodes1 = nullptr); 302 303 /// Try to select SBFX/UBFX instructions for ARM. 304 bool tryV6T2BitfieldExtractOp(SDNode *N, bool isSigned); 305 306 bool tryInsertVectorElt(SDNode *N); 307 308 // Select special operations if node forms integer ABS pattern 309 bool tryABSOp(SDNode *N); 310 311 bool tryReadRegister(SDNode *N); 312 bool tryWriteRegister(SDNode *N); 313 314 bool tryInlineAsm(SDNode *N); 315 316 void SelectCMPZ(SDNode *N, bool &SwitchEQNEToPLMI); 317 318 void SelectCMP_SWAP(SDNode *N); 319 320 /// SelectInlineAsmMemoryOperand - Implement addressing mode selection for 321 /// inline asm expressions. 322 bool SelectInlineAsmMemoryOperand(const SDValue &Op, unsigned ConstraintID, 323 std::vector<SDValue> &OutOps) override; 324 325 // Form pairs of consecutive R, S, D, or Q registers. 326 SDNode *createGPRPairNode(EVT VT, SDValue V0, SDValue V1); 327 SDNode *createSRegPairNode(EVT VT, SDValue V0, SDValue V1); 328 SDNode *createDRegPairNode(EVT VT, SDValue V0, SDValue V1); 329 SDNode *createQRegPairNode(EVT VT, SDValue V0, SDValue V1); 330 331 // Form sequences of 4 consecutive S, D, or Q registers. 332 SDNode *createQuadSRegsNode(EVT VT, SDValue V0, SDValue V1, SDValue V2, SDValue V3); 333 SDNode *createQuadDRegsNode(EVT VT, SDValue V0, SDValue V1, SDValue V2, SDValue V3); 334 SDNode *createQuadQRegsNode(EVT VT, SDValue V0, SDValue V1, SDValue V2, SDValue V3); 335 336 // Get the alignment operand for a NEON VLD or VST instruction. 337 SDValue GetVLDSTAlign(SDValue Align, const SDLoc &dl, unsigned NumVecs, 338 bool is64BitVector); 339 340 /// Checks if N is a multiplication by a constant where we can extract out a 341 /// power of two from the constant so that it can be used in a shift, but only 342 /// if it simplifies the materialization of the constant. Returns true if it 343 /// is, and assigns to PowerOfTwo the power of two that should be extracted 344 /// out and to NewMulConst the new constant to be multiplied by. 345 bool canExtractShiftFromMul(const SDValue &N, unsigned MaxShift, 346 unsigned &PowerOfTwo, SDValue &NewMulConst) const; 347 348 /// Replace N with M in CurDAG, in a way that also ensures that M gets 349 /// selected when N would have been selected. 350 void replaceDAGValue(const SDValue &N, SDValue M); 351 }; 352 } 353 354 /// isInt32Immediate - This method tests to see if the node is a 32-bit constant 355 /// operand. If so Imm will receive the 32-bit value. 356 static bool isInt32Immediate(SDNode *N, unsigned &Imm) { 357 if (N->getOpcode() == ISD::Constant && N->getValueType(0) == MVT::i32) { 358 Imm = cast<ConstantSDNode>(N)->getZExtValue(); 359 return true; 360 } 361 return false; 362 } 363 364 // isInt32Immediate - This method tests to see if a constant operand. 365 // If so Imm will receive the 32 bit value. 366 static bool isInt32Immediate(SDValue N, unsigned &Imm) { 367 return isInt32Immediate(N.getNode(), Imm); 368 } 369 370 // isOpcWithIntImmediate - This method tests to see if the node is a specific 371 // opcode and that it has a immediate integer right operand. 372 // If so Imm will receive the 32 bit value. 373 static bool isOpcWithIntImmediate(SDNode *N, unsigned Opc, unsigned& Imm) { 374 return N->getOpcode() == Opc && 375 isInt32Immediate(N->getOperand(1).getNode(), Imm); 376 } 377 378 /// Check whether a particular node is a constant value representable as 379 /// (N * Scale) where (N in [\p RangeMin, \p RangeMax). 380 /// 381 /// \param ScaledConstant [out] - On success, the pre-scaled constant value. 382 static bool isScaledConstantInRange(SDValue Node, int Scale, 383 int RangeMin, int RangeMax, 384 int &ScaledConstant) { 385 assert(Scale > 0 && "Invalid scale!"); 386 387 // Check that this is a constant. 388 const ConstantSDNode *C = dyn_cast<ConstantSDNode>(Node); 389 if (!C) 390 return false; 391 392 ScaledConstant = (int) C->getZExtValue(); 393 if ((ScaledConstant % Scale) != 0) 394 return false; 395 396 ScaledConstant /= Scale; 397 return ScaledConstant >= RangeMin && ScaledConstant < RangeMax; 398 } 399 400 void ARMDAGToDAGISel::PreprocessISelDAG() { 401 if (!Subtarget->hasV6T2Ops()) 402 return; 403 404 bool isThumb2 = Subtarget->isThumb(); 405 for (SelectionDAG::allnodes_iterator I = CurDAG->allnodes_begin(), 406 E = CurDAG->allnodes_end(); I != E; ) { 407 SDNode *N = &*I++; // Preincrement iterator to avoid invalidation issues. 408 409 if (N->getOpcode() != ISD::ADD) 410 continue; 411 412 // Look for (add X1, (and (srl X2, c1), c2)) where c2 is constant with 413 // leading zeros, followed by consecutive set bits, followed by 1 or 2 414 // trailing zeros, e.g. 1020. 415 // Transform the expression to 416 // (add X1, (shl (and (srl X2, c1), (c2>>tz)), tz)) where tz is the number 417 // of trailing zeros of c2. The left shift would be folded as an shifter 418 // operand of 'add' and the 'and' and 'srl' would become a bits extraction 419 // node (UBFX). 420 421 SDValue N0 = N->getOperand(0); 422 SDValue N1 = N->getOperand(1); 423 unsigned And_imm = 0; 424 if (!isOpcWithIntImmediate(N1.getNode(), ISD::AND, And_imm)) { 425 if (isOpcWithIntImmediate(N0.getNode(), ISD::AND, And_imm)) 426 std::swap(N0, N1); 427 } 428 if (!And_imm) 429 continue; 430 431 // Check if the AND mask is an immediate of the form: 000.....1111111100 432 unsigned TZ = countTrailingZeros(And_imm); 433 if (TZ != 1 && TZ != 2) 434 // Be conservative here. Shifter operands aren't always free. e.g. On 435 // Swift, left shifter operand of 1 / 2 for free but others are not. 436 // e.g. 437 // ubfx r3, r1, #16, #8 438 // ldr.w r3, [r0, r3, lsl #2] 439 // vs. 440 // mov.w r9, #1020 441 // and.w r2, r9, r1, lsr #14 442 // ldr r2, [r0, r2] 443 continue; 444 And_imm >>= TZ; 445 if (And_imm & (And_imm + 1)) 446 continue; 447 448 // Look for (and (srl X, c1), c2). 449 SDValue Srl = N1.getOperand(0); 450 unsigned Srl_imm = 0; 451 if (!isOpcWithIntImmediate(Srl.getNode(), ISD::SRL, Srl_imm) || 452 (Srl_imm <= 2)) 453 continue; 454 455 // Make sure first operand is not a shifter operand which would prevent 456 // folding of the left shift. 457 SDValue CPTmp0; 458 SDValue CPTmp1; 459 SDValue CPTmp2; 460 if (isThumb2) { 461 if (SelectImmShifterOperand(N0, CPTmp0, CPTmp1)) 462 continue; 463 } else { 464 if (SelectImmShifterOperand(N0, CPTmp0, CPTmp1) || 465 SelectRegShifterOperand(N0, CPTmp0, CPTmp1, CPTmp2)) 466 continue; 467 } 468 469 // Now make the transformation. 470 Srl = CurDAG->getNode(ISD::SRL, SDLoc(Srl), MVT::i32, 471 Srl.getOperand(0), 472 CurDAG->getConstant(Srl_imm + TZ, SDLoc(Srl), 473 MVT::i32)); 474 N1 = CurDAG->getNode(ISD::AND, SDLoc(N1), MVT::i32, 475 Srl, 476 CurDAG->getConstant(And_imm, SDLoc(Srl), MVT::i32)); 477 N1 = CurDAG->getNode(ISD::SHL, SDLoc(N1), MVT::i32, 478 N1, CurDAG->getConstant(TZ, SDLoc(Srl), MVT::i32)); 479 CurDAG->UpdateNodeOperands(N, N0, N1); 480 } 481 } 482 483 /// hasNoVMLxHazardUse - Return true if it's desirable to select a FP MLA / MLS 484 /// node. VFP / NEON fp VMLA / VMLS instructions have special RAW hazards (at 485 /// least on current ARM implementations) which should be avoidded. 486 bool ARMDAGToDAGISel::hasNoVMLxHazardUse(SDNode *N) const { 487 if (OptLevel == CodeGenOpt::None) 488 return true; 489 490 if (!Subtarget->hasVMLxHazards()) 491 return true; 492 493 if (!N->hasOneUse()) 494 return false; 495 496 SDNode *Use = *N->use_begin(); 497 if (Use->getOpcode() == ISD::CopyToReg) 498 return true; 499 if (Use->isMachineOpcode()) { 500 const ARMBaseInstrInfo *TII = static_cast<const ARMBaseInstrInfo *>( 501 CurDAG->getSubtarget().getInstrInfo()); 502 503 const MCInstrDesc &MCID = TII->get(Use->getMachineOpcode()); 504 if (MCID.mayStore()) 505 return true; 506 unsigned Opcode = MCID.getOpcode(); 507 if (Opcode == ARM::VMOVRS || Opcode == ARM::VMOVRRD) 508 return true; 509 // vmlx feeding into another vmlx. We actually want to unfold 510 // the use later in the MLxExpansion pass. e.g. 511 // vmla 512 // vmla (stall 8 cycles) 513 // 514 // vmul (5 cycles) 515 // vadd (5 cycles) 516 // vmla 517 // This adds up to about 18 - 19 cycles. 518 // 519 // vmla 520 // vmul (stall 4 cycles) 521 // vadd adds up to about 14 cycles. 522 return TII->isFpMLxInstruction(Opcode); 523 } 524 525 return false; 526 } 527 528 bool ARMDAGToDAGISel::isShifterOpProfitable(const SDValue &Shift, 529 ARM_AM::ShiftOpc ShOpcVal, 530 unsigned ShAmt) { 531 if (!Subtarget->isLikeA9() && !Subtarget->isSwift()) 532 return true; 533 if (Shift.hasOneUse()) 534 return true; 535 // R << 2 is free. 536 return ShOpcVal == ARM_AM::lsl && 537 (ShAmt == 2 || (Subtarget->isSwift() && ShAmt == 1)); 538 } 539 540 bool ARMDAGToDAGISel::canExtractShiftFromMul(const SDValue &N, 541 unsigned MaxShift, 542 unsigned &PowerOfTwo, 543 SDValue &NewMulConst) const { 544 assert(N.getOpcode() == ISD::MUL); 545 assert(MaxShift > 0); 546 547 // If the multiply is used in more than one place then changing the constant 548 // will make other uses incorrect, so don't. 549 if (!N.hasOneUse()) return false; 550 // Check if the multiply is by a constant 551 ConstantSDNode *MulConst = dyn_cast<ConstantSDNode>(N.getOperand(1)); 552 if (!MulConst) return false; 553 // If the constant is used in more than one place then modifying it will mean 554 // we need to materialize two constants instead of one, which is a bad idea. 555 if (!MulConst->hasOneUse()) return false; 556 unsigned MulConstVal = MulConst->getZExtValue(); 557 if (MulConstVal == 0) return false; 558 559 // Find the largest power of 2 that MulConstVal is a multiple of 560 PowerOfTwo = MaxShift; 561 while ((MulConstVal % (1 << PowerOfTwo)) != 0) { 562 --PowerOfTwo; 563 if (PowerOfTwo == 0) return false; 564 } 565 566 // Only optimise if the new cost is better 567 unsigned NewMulConstVal = MulConstVal / (1 << PowerOfTwo); 568 NewMulConst = CurDAG->getConstant(NewMulConstVal, SDLoc(N), MVT::i32); 569 unsigned OldCost = ConstantMaterializationCost(MulConstVal, Subtarget); 570 unsigned NewCost = ConstantMaterializationCost(NewMulConstVal, Subtarget); 571 return NewCost < OldCost; 572 } 573 574 void ARMDAGToDAGISel::replaceDAGValue(const SDValue &N, SDValue M) { 575 CurDAG->RepositionNode(N.getNode()->getIterator(), M.getNode()); 576 ReplaceUses(N, M); 577 } 578 579 bool ARMDAGToDAGISel::SelectImmShifterOperand(SDValue N, 580 SDValue &BaseReg, 581 SDValue &Opc, 582 bool CheckProfitability) { 583 if (DisableShifterOp) 584 return false; 585 586 // If N is a multiply-by-constant and it's profitable to extract a shift and 587 // use it in a shifted operand do so. 588 if (N.getOpcode() == ISD::MUL) { 589 unsigned PowerOfTwo = 0; 590 SDValue NewMulConst; 591 if (canExtractShiftFromMul(N, 31, PowerOfTwo, NewMulConst)) { 592 HandleSDNode Handle(N); 593 SDLoc Loc(N); 594 replaceDAGValue(N.getOperand(1), NewMulConst); 595 BaseReg = Handle.getValue(); 596 Opc = CurDAG->getTargetConstant( 597 ARM_AM::getSORegOpc(ARM_AM::lsl, PowerOfTwo), Loc, MVT::i32); 598 return true; 599 } 600 } 601 602 ARM_AM::ShiftOpc ShOpcVal = ARM_AM::getShiftOpcForNode(N.getOpcode()); 603 604 // Don't match base register only case. That is matched to a separate 605 // lower complexity pattern with explicit register operand. 606 if (ShOpcVal == ARM_AM::no_shift) return false; 607 608 BaseReg = N.getOperand(0); 609 unsigned ShImmVal = 0; 610 ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N.getOperand(1)); 611 if (!RHS) return false; 612 ShImmVal = RHS->getZExtValue() & 31; 613 Opc = CurDAG->getTargetConstant(ARM_AM::getSORegOpc(ShOpcVal, ShImmVal), 614 SDLoc(N), MVT::i32); 615 return true; 616 } 617 618 bool ARMDAGToDAGISel::SelectRegShifterOperand(SDValue N, 619 SDValue &BaseReg, 620 SDValue &ShReg, 621 SDValue &Opc, 622 bool CheckProfitability) { 623 if (DisableShifterOp) 624 return false; 625 626 ARM_AM::ShiftOpc ShOpcVal = ARM_AM::getShiftOpcForNode(N.getOpcode()); 627 628 // Don't match base register only case. That is matched to a separate 629 // lower complexity pattern with explicit register operand. 630 if (ShOpcVal == ARM_AM::no_shift) return false; 631 632 BaseReg = N.getOperand(0); 633 unsigned ShImmVal = 0; 634 ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N.getOperand(1)); 635 if (RHS) return false; 636 637 ShReg = N.getOperand(1); 638 if (CheckProfitability && !isShifterOpProfitable(N, ShOpcVal, ShImmVal)) 639 return false; 640 Opc = CurDAG->getTargetConstant(ARM_AM::getSORegOpc(ShOpcVal, ShImmVal), 641 SDLoc(N), MVT::i32); 642 return true; 643 } 644 645 // Determine whether an ISD::OR's operands are suitable to turn the operation 646 // into an addition, which often has more compact encodings. 647 bool ARMDAGToDAGISel::SelectAddLikeOr(SDNode *Parent, SDValue N, SDValue &Out) { 648 assert(Parent->getOpcode() == ISD::OR && "unexpected parent"); 649 Out = N; 650 return CurDAG->haveNoCommonBitsSet(N, Parent->getOperand(1)); 651 } 652 653 654 bool ARMDAGToDAGISel::SelectAddrModeImm12(SDValue N, 655 SDValue &Base, 656 SDValue &OffImm) { 657 // Match simple R + imm12 operands. 658 659 // Base only. 660 if (N.getOpcode() != ISD::ADD && N.getOpcode() != ISD::SUB && 661 !CurDAG->isBaseWithConstantOffset(N)) { 662 if (N.getOpcode() == ISD::FrameIndex) { 663 // Match frame index. 664 int FI = cast<FrameIndexSDNode>(N)->getIndex(); 665 Base = CurDAG->getTargetFrameIndex( 666 FI, TLI->getPointerTy(CurDAG->getDataLayout())); 667 OffImm = CurDAG->getTargetConstant(0, SDLoc(N), MVT::i32); 668 return true; 669 } 670 671 if (N.getOpcode() == ARMISD::Wrapper && 672 N.getOperand(0).getOpcode() != ISD::TargetGlobalAddress && 673 N.getOperand(0).getOpcode() != ISD::TargetExternalSymbol && 674 N.getOperand(0).getOpcode() != ISD::TargetGlobalTLSAddress) { 675 Base = N.getOperand(0); 676 } else 677 Base = N; 678 OffImm = CurDAG->getTargetConstant(0, SDLoc(N), MVT::i32); 679 return true; 680 } 681 682 if (ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N.getOperand(1))) { 683 int RHSC = (int)RHS->getSExtValue(); 684 if (N.getOpcode() == ISD::SUB) 685 RHSC = -RHSC; 686 687 if (RHSC > -0x1000 && RHSC < 0x1000) { // 12 bits 688 Base = N.getOperand(0); 689 if (Base.getOpcode() == ISD::FrameIndex) { 690 int FI = cast<FrameIndexSDNode>(Base)->getIndex(); 691 Base = CurDAG->getTargetFrameIndex( 692 FI, TLI->getPointerTy(CurDAG->getDataLayout())); 693 } 694 OffImm = CurDAG->getTargetConstant(RHSC, SDLoc(N), MVT::i32); 695 return true; 696 } 697 } 698 699 // Base only. 700 Base = N; 701 OffImm = CurDAG->getTargetConstant(0, SDLoc(N), MVT::i32); 702 return true; 703 } 704 705 706 707 bool ARMDAGToDAGISel::SelectLdStSOReg(SDValue N, SDValue &Base, SDValue &Offset, 708 SDValue &Opc) { 709 if (N.getOpcode() == ISD::MUL && 710 ((!Subtarget->isLikeA9() && !Subtarget->isSwift()) || N.hasOneUse())) { 711 if (ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N.getOperand(1))) { 712 // X * [3,5,9] -> X + X * [2,4,8] etc. 713 int RHSC = (int)RHS->getZExtValue(); 714 if (RHSC & 1) { 715 RHSC = RHSC & ~1; 716 ARM_AM::AddrOpc AddSub = ARM_AM::add; 717 if (RHSC < 0) { 718 AddSub = ARM_AM::sub; 719 RHSC = - RHSC; 720 } 721 if (isPowerOf2_32(RHSC)) { 722 unsigned ShAmt = Log2_32(RHSC); 723 Base = Offset = N.getOperand(0); 724 Opc = CurDAG->getTargetConstant(ARM_AM::getAM2Opc(AddSub, ShAmt, 725 ARM_AM::lsl), 726 SDLoc(N), MVT::i32); 727 return true; 728 } 729 } 730 } 731 } 732 733 if (N.getOpcode() != ISD::ADD && N.getOpcode() != ISD::SUB && 734 // ISD::OR that is equivalent to an ISD::ADD. 735 !CurDAG->isBaseWithConstantOffset(N)) 736 return false; 737 738 // Leave simple R +/- imm12 operands for LDRi12 739 if (N.getOpcode() == ISD::ADD || N.getOpcode() == ISD::OR) { 740 int RHSC; 741 if (isScaledConstantInRange(N.getOperand(1), /*Scale=*/1, 742 -0x1000+1, 0x1000, RHSC)) // 12 bits. 743 return false; 744 } 745 746 // Otherwise this is R +/- [possibly shifted] R. 747 ARM_AM::AddrOpc AddSub = N.getOpcode() == ISD::SUB ? ARM_AM::sub:ARM_AM::add; 748 ARM_AM::ShiftOpc ShOpcVal = 749 ARM_AM::getShiftOpcForNode(N.getOperand(1).getOpcode()); 750 unsigned ShAmt = 0; 751 752 Base = N.getOperand(0); 753 Offset = N.getOperand(1); 754 755 if (ShOpcVal != ARM_AM::no_shift) { 756 // Check to see if the RHS of the shift is a constant, if not, we can't fold 757 // it. 758 if (ConstantSDNode *Sh = 759 dyn_cast<ConstantSDNode>(N.getOperand(1).getOperand(1))) { 760 ShAmt = Sh->getZExtValue(); 761 if (isShifterOpProfitable(Offset, ShOpcVal, ShAmt)) 762 Offset = N.getOperand(1).getOperand(0); 763 else { 764 ShAmt = 0; 765 ShOpcVal = ARM_AM::no_shift; 766 } 767 } else { 768 ShOpcVal = ARM_AM::no_shift; 769 } 770 } 771 772 // Try matching (R shl C) + (R). 773 if (N.getOpcode() != ISD::SUB && ShOpcVal == ARM_AM::no_shift && 774 !(Subtarget->isLikeA9() || Subtarget->isSwift() || 775 N.getOperand(0).hasOneUse())) { 776 ShOpcVal = ARM_AM::getShiftOpcForNode(N.getOperand(0).getOpcode()); 777 if (ShOpcVal != ARM_AM::no_shift) { 778 // Check to see if the RHS of the shift is a constant, if not, we can't 779 // fold it. 780 if (ConstantSDNode *Sh = 781 dyn_cast<ConstantSDNode>(N.getOperand(0).getOperand(1))) { 782 ShAmt = Sh->getZExtValue(); 783 if (isShifterOpProfitable(N.getOperand(0), ShOpcVal, ShAmt)) { 784 Offset = N.getOperand(0).getOperand(0); 785 Base = N.getOperand(1); 786 } else { 787 ShAmt = 0; 788 ShOpcVal = ARM_AM::no_shift; 789 } 790 } else { 791 ShOpcVal = ARM_AM::no_shift; 792 } 793 } 794 } 795 796 // If Offset is a multiply-by-constant and it's profitable to extract a shift 797 // and use it in a shifted operand do so. 798 if (Offset.getOpcode() == ISD::MUL && N.hasOneUse()) { 799 unsigned PowerOfTwo = 0; 800 SDValue NewMulConst; 801 if (canExtractShiftFromMul(Offset, 31, PowerOfTwo, NewMulConst)) { 802 HandleSDNode Handle(Offset); 803 replaceDAGValue(Offset.getOperand(1), NewMulConst); 804 Offset = Handle.getValue(); 805 ShAmt = PowerOfTwo; 806 ShOpcVal = ARM_AM::lsl; 807 } 808 } 809 810 Opc = CurDAG->getTargetConstant(ARM_AM::getAM2Opc(AddSub, ShAmt, ShOpcVal), 811 SDLoc(N), MVT::i32); 812 return true; 813 } 814 815 bool ARMDAGToDAGISel::SelectAddrMode2OffsetReg(SDNode *Op, SDValue N, 816 SDValue &Offset, SDValue &Opc) { 817 unsigned Opcode = Op->getOpcode(); 818 ISD::MemIndexedMode AM = (Opcode == ISD::LOAD) 819 ? cast<LoadSDNode>(Op)->getAddressingMode() 820 : cast<StoreSDNode>(Op)->getAddressingMode(); 821 ARM_AM::AddrOpc AddSub = (AM == ISD::PRE_INC || AM == ISD::POST_INC) 822 ? ARM_AM::add : ARM_AM::sub; 823 int Val; 824 if (isScaledConstantInRange(N, /*Scale=*/1, 0, 0x1000, Val)) 825 return false; 826 827 Offset = N; 828 ARM_AM::ShiftOpc ShOpcVal = ARM_AM::getShiftOpcForNode(N.getOpcode()); 829 unsigned ShAmt = 0; 830 if (ShOpcVal != ARM_AM::no_shift) { 831 // Check to see if the RHS of the shift is a constant, if not, we can't fold 832 // it. 833 if (ConstantSDNode *Sh = dyn_cast<ConstantSDNode>(N.getOperand(1))) { 834 ShAmt = Sh->getZExtValue(); 835 if (isShifterOpProfitable(N, ShOpcVal, ShAmt)) 836 Offset = N.getOperand(0); 837 else { 838 ShAmt = 0; 839 ShOpcVal = ARM_AM::no_shift; 840 } 841 } else { 842 ShOpcVal = ARM_AM::no_shift; 843 } 844 } 845 846 Opc = CurDAG->getTargetConstant(ARM_AM::getAM2Opc(AddSub, ShAmt, ShOpcVal), 847 SDLoc(N), MVT::i32); 848 return true; 849 } 850 851 bool ARMDAGToDAGISel::SelectAddrMode2OffsetImmPre(SDNode *Op, SDValue N, 852 SDValue &Offset, SDValue &Opc) { 853 unsigned Opcode = Op->getOpcode(); 854 ISD::MemIndexedMode AM = (Opcode == ISD::LOAD) 855 ? cast<LoadSDNode>(Op)->getAddressingMode() 856 : cast<StoreSDNode>(Op)->getAddressingMode(); 857 ARM_AM::AddrOpc AddSub = (AM == ISD::PRE_INC || AM == ISD::POST_INC) 858 ? ARM_AM::add : ARM_AM::sub; 859 int Val; 860 if (isScaledConstantInRange(N, /*Scale=*/1, 0, 0x1000, Val)) { // 12 bits. 861 if (AddSub == ARM_AM::sub) Val *= -1; 862 Offset = CurDAG->getRegister(0, MVT::i32); 863 Opc = CurDAG->getTargetConstant(Val, SDLoc(Op), MVT::i32); 864 return true; 865 } 866 867 return false; 868 } 869 870 871 bool ARMDAGToDAGISel::SelectAddrMode2OffsetImm(SDNode *Op, SDValue N, 872 SDValue &Offset, SDValue &Opc) { 873 unsigned Opcode = Op->getOpcode(); 874 ISD::MemIndexedMode AM = (Opcode == ISD::LOAD) 875 ? cast<LoadSDNode>(Op)->getAddressingMode() 876 : cast<StoreSDNode>(Op)->getAddressingMode(); 877 ARM_AM::AddrOpc AddSub = (AM == ISD::PRE_INC || AM == ISD::POST_INC) 878 ? ARM_AM::add : ARM_AM::sub; 879 int Val; 880 if (isScaledConstantInRange(N, /*Scale=*/1, 0, 0x1000, Val)) { // 12 bits. 881 Offset = CurDAG->getRegister(0, MVT::i32); 882 Opc = CurDAG->getTargetConstant(ARM_AM::getAM2Opc(AddSub, Val, 883 ARM_AM::no_shift), 884 SDLoc(Op), MVT::i32); 885 return true; 886 } 887 888 return false; 889 } 890 891 bool ARMDAGToDAGISel::SelectAddrOffsetNone(SDValue N, SDValue &Base) { 892 Base = N; 893 return true; 894 } 895 896 bool ARMDAGToDAGISel::SelectAddrMode3(SDValue N, 897 SDValue &Base, SDValue &Offset, 898 SDValue &Opc) { 899 if (N.getOpcode() == ISD::SUB) { 900 // X - C is canonicalize to X + -C, no need to handle it here. 901 Base = N.getOperand(0); 902 Offset = N.getOperand(1); 903 Opc = CurDAG->getTargetConstant(ARM_AM::getAM3Opc(ARM_AM::sub, 0), SDLoc(N), 904 MVT::i32); 905 return true; 906 } 907 908 if (!CurDAG->isBaseWithConstantOffset(N)) { 909 Base = N; 910 if (N.getOpcode() == ISD::FrameIndex) { 911 int FI = cast<FrameIndexSDNode>(N)->getIndex(); 912 Base = CurDAG->getTargetFrameIndex( 913 FI, TLI->getPointerTy(CurDAG->getDataLayout())); 914 } 915 Offset = CurDAG->getRegister(0, MVT::i32); 916 Opc = CurDAG->getTargetConstant(ARM_AM::getAM3Opc(ARM_AM::add, 0), SDLoc(N), 917 MVT::i32); 918 return true; 919 } 920 921 // If the RHS is +/- imm8, fold into addr mode. 922 int RHSC; 923 if (isScaledConstantInRange(N.getOperand(1), /*Scale=*/1, 924 -256 + 1, 256, RHSC)) { // 8 bits. 925 Base = N.getOperand(0); 926 if (Base.getOpcode() == ISD::FrameIndex) { 927 int FI = cast<FrameIndexSDNode>(Base)->getIndex(); 928 Base = CurDAG->getTargetFrameIndex( 929 FI, TLI->getPointerTy(CurDAG->getDataLayout())); 930 } 931 Offset = CurDAG->getRegister(0, MVT::i32); 932 933 ARM_AM::AddrOpc AddSub = ARM_AM::add; 934 if (RHSC < 0) { 935 AddSub = ARM_AM::sub; 936 RHSC = -RHSC; 937 } 938 Opc = CurDAG->getTargetConstant(ARM_AM::getAM3Opc(AddSub, RHSC), SDLoc(N), 939 MVT::i32); 940 return true; 941 } 942 943 Base = N.getOperand(0); 944 Offset = N.getOperand(1); 945 Opc = CurDAG->getTargetConstant(ARM_AM::getAM3Opc(ARM_AM::add, 0), SDLoc(N), 946 MVT::i32); 947 return true; 948 } 949 950 bool ARMDAGToDAGISel::SelectAddrMode3Offset(SDNode *Op, SDValue N, 951 SDValue &Offset, SDValue &Opc) { 952 unsigned Opcode = Op->getOpcode(); 953 ISD::MemIndexedMode AM = (Opcode == ISD::LOAD) 954 ? cast<LoadSDNode>(Op)->getAddressingMode() 955 : cast<StoreSDNode>(Op)->getAddressingMode(); 956 ARM_AM::AddrOpc AddSub = (AM == ISD::PRE_INC || AM == ISD::POST_INC) 957 ? ARM_AM::add : ARM_AM::sub; 958 int Val; 959 if (isScaledConstantInRange(N, /*Scale=*/1, 0, 256, Val)) { // 12 bits. 960 Offset = CurDAG->getRegister(0, MVT::i32); 961 Opc = CurDAG->getTargetConstant(ARM_AM::getAM3Opc(AddSub, Val), SDLoc(Op), 962 MVT::i32); 963 return true; 964 } 965 966 Offset = N; 967 Opc = CurDAG->getTargetConstant(ARM_AM::getAM3Opc(AddSub, 0), SDLoc(Op), 968 MVT::i32); 969 return true; 970 } 971 972 bool ARMDAGToDAGISel::IsAddressingMode5(SDValue N, SDValue &Base, SDValue &Offset, 973 bool FP16) { 974 if (!CurDAG->isBaseWithConstantOffset(N)) { 975 Base = N; 976 if (N.getOpcode() == ISD::FrameIndex) { 977 int FI = cast<FrameIndexSDNode>(N)->getIndex(); 978 Base = CurDAG->getTargetFrameIndex( 979 FI, TLI->getPointerTy(CurDAG->getDataLayout())); 980 } else if (N.getOpcode() == ARMISD::Wrapper && 981 N.getOperand(0).getOpcode() != ISD::TargetGlobalAddress && 982 N.getOperand(0).getOpcode() != ISD::TargetExternalSymbol && 983 N.getOperand(0).getOpcode() != ISD::TargetGlobalTLSAddress) { 984 Base = N.getOperand(0); 985 } 986 Offset = CurDAG->getTargetConstant(ARM_AM::getAM5Opc(ARM_AM::add, 0), 987 SDLoc(N), MVT::i32); 988 return true; 989 } 990 991 // If the RHS is +/- imm8, fold into addr mode. 992 int RHSC; 993 const int Scale = FP16 ? 2 : 4; 994 995 if (isScaledConstantInRange(N.getOperand(1), Scale, -255, 256, RHSC)) { 996 Base = N.getOperand(0); 997 if (Base.getOpcode() == ISD::FrameIndex) { 998 int FI = cast<FrameIndexSDNode>(Base)->getIndex(); 999 Base = CurDAG->getTargetFrameIndex( 1000 FI, TLI->getPointerTy(CurDAG->getDataLayout())); 1001 } 1002 1003 ARM_AM::AddrOpc AddSub = ARM_AM::add; 1004 if (RHSC < 0) { 1005 AddSub = ARM_AM::sub; 1006 RHSC = -RHSC; 1007 } 1008 1009 if (FP16) 1010 Offset = CurDAG->getTargetConstant(ARM_AM::getAM5FP16Opc(AddSub, RHSC), 1011 SDLoc(N), MVT::i32); 1012 else 1013 Offset = CurDAG->getTargetConstant(ARM_AM::getAM5Opc(AddSub, RHSC), 1014 SDLoc(N), MVT::i32); 1015 1016 return true; 1017 } 1018 1019 Base = N; 1020 1021 if (FP16) 1022 Offset = CurDAG->getTargetConstant(ARM_AM::getAM5FP16Opc(ARM_AM::add, 0), 1023 SDLoc(N), MVT::i32); 1024 else 1025 Offset = CurDAG->getTargetConstant(ARM_AM::getAM5Opc(ARM_AM::add, 0), 1026 SDLoc(N), MVT::i32); 1027 1028 return true; 1029 } 1030 1031 bool ARMDAGToDAGISel::SelectAddrMode5(SDValue N, 1032 SDValue &Base, SDValue &Offset) { 1033 return IsAddressingMode5(N, Base, Offset, /*FP16=*/ false); 1034 } 1035 1036 bool ARMDAGToDAGISel::SelectAddrMode5FP16(SDValue N, 1037 SDValue &Base, SDValue &Offset) { 1038 return IsAddressingMode5(N, Base, Offset, /*FP16=*/ true); 1039 } 1040 1041 bool ARMDAGToDAGISel::SelectAddrMode6(SDNode *Parent, SDValue N, SDValue &Addr, 1042 SDValue &Align) { 1043 Addr = N; 1044 1045 unsigned Alignment = 0; 1046 1047 MemSDNode *MemN = cast<MemSDNode>(Parent); 1048 1049 if (isa<LSBaseSDNode>(MemN) || 1050 ((MemN->getOpcode() == ARMISD::VST1_UPD || 1051 MemN->getOpcode() == ARMISD::VLD1_UPD) && 1052 MemN->getConstantOperandVal(MemN->getNumOperands() - 1) == 1)) { 1053 // This case occurs only for VLD1-lane/dup and VST1-lane instructions. 1054 // The maximum alignment is equal to the memory size being referenced. 1055 unsigned MMOAlign = MemN->getAlignment(); 1056 unsigned MemSize = MemN->getMemoryVT().getSizeInBits() / 8; 1057 if (MMOAlign >= MemSize && MemSize > 1) 1058 Alignment = MemSize; 1059 } else { 1060 // All other uses of addrmode6 are for intrinsics. For now just record 1061 // the raw alignment value; it will be refined later based on the legal 1062 // alignment operands for the intrinsic. 1063 Alignment = MemN->getAlignment(); 1064 } 1065 1066 Align = CurDAG->getTargetConstant(Alignment, SDLoc(N), MVT::i32); 1067 return true; 1068 } 1069 1070 bool ARMDAGToDAGISel::SelectAddrMode6Offset(SDNode *Op, SDValue N, 1071 SDValue &Offset) { 1072 LSBaseSDNode *LdSt = cast<LSBaseSDNode>(Op); 1073 ISD::MemIndexedMode AM = LdSt->getAddressingMode(); 1074 if (AM != ISD::POST_INC) 1075 return false; 1076 Offset = N; 1077 if (ConstantSDNode *NC = dyn_cast<ConstantSDNode>(N)) { 1078 if (NC->getZExtValue() * 8 == LdSt->getMemoryVT().getSizeInBits()) 1079 Offset = CurDAG->getRegister(0, MVT::i32); 1080 } 1081 return true; 1082 } 1083 1084 bool ARMDAGToDAGISel::SelectAddrModePC(SDValue N, 1085 SDValue &Offset, SDValue &Label) { 1086 if (N.getOpcode() == ARMISD::PIC_ADD && N.hasOneUse()) { 1087 Offset = N.getOperand(0); 1088 SDValue N1 = N.getOperand(1); 1089 Label = CurDAG->getTargetConstant(cast<ConstantSDNode>(N1)->getZExtValue(), 1090 SDLoc(N), MVT::i32); 1091 return true; 1092 } 1093 1094 return false; 1095 } 1096 1097 1098 //===----------------------------------------------------------------------===// 1099 // Thumb Addressing Modes 1100 //===----------------------------------------------------------------------===// 1101 1102 static bool shouldUseZeroOffsetLdSt(SDValue N) { 1103 // Negative numbers are difficult to materialise in thumb1. If we are 1104 // selecting the add of a negative, instead try to select ri with a zero 1105 // offset, so create the add node directly which will become a sub. 1106 if (N.getOpcode() != ISD::ADD) 1107 return false; 1108 1109 // Look for an imm which is not legal for ld/st, but is legal for sub. 1110 if (auto C = dyn_cast<ConstantSDNode>(N.getOperand(1))) 1111 return C->getSExtValue() < 0 && C->getSExtValue() >= -255; 1112 1113 return false; 1114 } 1115 1116 bool ARMDAGToDAGISel::SelectThumbAddrModeRRSext(SDValue N, SDValue &Base, 1117 SDValue &Offset) { 1118 if (N.getOpcode() != ISD::ADD && !CurDAG->isBaseWithConstantOffset(N)) { 1119 ConstantSDNode *NC = dyn_cast<ConstantSDNode>(N); 1120 if (!NC || !NC->isNullValue()) 1121 return false; 1122 1123 Base = Offset = N; 1124 return true; 1125 } 1126 1127 Base = N.getOperand(0); 1128 Offset = N.getOperand(1); 1129 return true; 1130 } 1131 1132 bool ARMDAGToDAGISel::SelectThumbAddrModeRR(SDValue N, SDValue &Base, 1133 SDValue &Offset) { 1134 if (shouldUseZeroOffsetLdSt(N)) 1135 return false; // Select ri instead 1136 return SelectThumbAddrModeRRSext(N, Base, Offset); 1137 } 1138 1139 bool 1140 ARMDAGToDAGISel::SelectThumbAddrModeImm5S(SDValue N, unsigned Scale, 1141 SDValue &Base, SDValue &OffImm) { 1142 if (shouldUseZeroOffsetLdSt(N)) { 1143 Base = N; 1144 OffImm = CurDAG->getTargetConstant(0, SDLoc(N), MVT::i32); 1145 return true; 1146 } 1147 1148 if (!CurDAG->isBaseWithConstantOffset(N)) { 1149 if (N.getOpcode() == ISD::ADD) { 1150 return false; // We want to select register offset instead 1151 } else if (N.getOpcode() == ARMISD::Wrapper && 1152 N.getOperand(0).getOpcode() != ISD::TargetGlobalAddress && 1153 N.getOperand(0).getOpcode() != ISD::TargetExternalSymbol && 1154 N.getOperand(0).getOpcode() != ISD::TargetConstantPool && 1155 N.getOperand(0).getOpcode() != ISD::TargetGlobalTLSAddress) { 1156 Base = N.getOperand(0); 1157 } else { 1158 Base = N; 1159 } 1160 1161 OffImm = CurDAG->getTargetConstant(0, SDLoc(N), MVT::i32); 1162 return true; 1163 } 1164 1165 // If the RHS is + imm5 * scale, fold into addr mode. 1166 int RHSC; 1167 if (isScaledConstantInRange(N.getOperand(1), Scale, 0, 32, RHSC)) { 1168 Base = N.getOperand(0); 1169 OffImm = CurDAG->getTargetConstant(RHSC, SDLoc(N), MVT::i32); 1170 return true; 1171 } 1172 1173 // Offset is too large, so use register offset instead. 1174 return false; 1175 } 1176 1177 bool 1178 ARMDAGToDAGISel::SelectThumbAddrModeImm5S4(SDValue N, SDValue &Base, 1179 SDValue &OffImm) { 1180 return SelectThumbAddrModeImm5S(N, 4, Base, OffImm); 1181 } 1182 1183 bool 1184 ARMDAGToDAGISel::SelectThumbAddrModeImm5S2(SDValue N, SDValue &Base, 1185 SDValue &OffImm) { 1186 return SelectThumbAddrModeImm5S(N, 2, Base, OffImm); 1187 } 1188 1189 bool 1190 ARMDAGToDAGISel::SelectThumbAddrModeImm5S1(SDValue N, SDValue &Base, 1191 SDValue &OffImm) { 1192 return SelectThumbAddrModeImm5S(N, 1, Base, OffImm); 1193 } 1194 1195 bool ARMDAGToDAGISel::SelectThumbAddrModeSP(SDValue N, 1196 SDValue &Base, SDValue &OffImm) { 1197 if (N.getOpcode() == ISD::FrameIndex) { 1198 int FI = cast<FrameIndexSDNode>(N)->getIndex(); 1199 // Only multiples of 4 are allowed for the offset, so the frame object 1200 // alignment must be at least 4. 1201 MachineFrameInfo &MFI = MF->getFrameInfo(); 1202 if (MFI.getObjectAlign(FI) < Align(4)) 1203 MFI.setObjectAlignment(FI, Align(4)); 1204 Base = CurDAG->getTargetFrameIndex( 1205 FI, TLI->getPointerTy(CurDAG->getDataLayout())); 1206 OffImm = CurDAG->getTargetConstant(0, SDLoc(N), MVT::i32); 1207 return true; 1208 } 1209 1210 if (!CurDAG->isBaseWithConstantOffset(N)) 1211 return false; 1212 1213 if (N.getOperand(0).getOpcode() == ISD::FrameIndex) { 1214 // If the RHS is + imm8 * scale, fold into addr mode. 1215 int RHSC; 1216 if (isScaledConstantInRange(N.getOperand(1), /*Scale=*/4, 0, 256, RHSC)) { 1217 Base = N.getOperand(0); 1218 int FI = cast<FrameIndexSDNode>(Base)->getIndex(); 1219 // Make sure the offset is inside the object, or we might fail to 1220 // allocate an emergency spill slot. (An out-of-range access is UB, but 1221 // it could show up anyway.) 1222 MachineFrameInfo &MFI = MF->getFrameInfo(); 1223 if (RHSC * 4 < MFI.getObjectSize(FI)) { 1224 // For LHS+RHS to result in an offset that's a multiple of 4 the object 1225 // indexed by the LHS must be 4-byte aligned. 1226 if (!MFI.isFixedObjectIndex(FI) && MFI.getObjectAlign(FI) < Align(4)) 1227 MFI.setObjectAlignment(FI, Align(4)); 1228 if (MFI.getObjectAlign(FI) >= Align(4)) { 1229 Base = CurDAG->getTargetFrameIndex( 1230 FI, TLI->getPointerTy(CurDAG->getDataLayout())); 1231 OffImm = CurDAG->getTargetConstant(RHSC, SDLoc(N), MVT::i32); 1232 return true; 1233 } 1234 } 1235 } 1236 } 1237 1238 return false; 1239 } 1240 1241 template <unsigned Shift> 1242 bool ARMDAGToDAGISel::SelectTAddrModeImm7(SDValue N, SDValue &Base, 1243 SDValue &OffImm) { 1244 if (N.getOpcode() == ISD::SUB || CurDAG->isBaseWithConstantOffset(N)) { 1245 int RHSC; 1246 if (isScaledConstantInRange(N.getOperand(1), 1 << Shift, -0x7f, 0x80, 1247 RHSC)) { 1248 Base = N.getOperand(0); 1249 if (N.getOpcode() == ISD::SUB) 1250 RHSC = -RHSC; 1251 OffImm = 1252 CurDAG->getTargetConstant(RHSC * (1 << Shift), SDLoc(N), MVT::i32); 1253 return true; 1254 } 1255 } 1256 1257 // Base only. 1258 Base = N; 1259 OffImm = CurDAG->getTargetConstant(0, SDLoc(N), MVT::i32); 1260 return true; 1261 } 1262 1263 1264 //===----------------------------------------------------------------------===// 1265 // Thumb 2 Addressing Modes 1266 //===----------------------------------------------------------------------===// 1267 1268 1269 bool ARMDAGToDAGISel::SelectT2AddrModeImm12(SDValue N, 1270 SDValue &Base, SDValue &OffImm) { 1271 // Match simple R + imm12 operands. 1272 1273 // Base only. 1274 if (N.getOpcode() != ISD::ADD && N.getOpcode() != ISD::SUB && 1275 !CurDAG->isBaseWithConstantOffset(N)) { 1276 if (N.getOpcode() == ISD::FrameIndex) { 1277 // Match frame index. 1278 int FI = cast<FrameIndexSDNode>(N)->getIndex(); 1279 Base = CurDAG->getTargetFrameIndex( 1280 FI, TLI->getPointerTy(CurDAG->getDataLayout())); 1281 OffImm = CurDAG->getTargetConstant(0, SDLoc(N), MVT::i32); 1282 return true; 1283 } 1284 1285 if (N.getOpcode() == ARMISD::Wrapper && 1286 N.getOperand(0).getOpcode() != ISD::TargetGlobalAddress && 1287 N.getOperand(0).getOpcode() != ISD::TargetExternalSymbol && 1288 N.getOperand(0).getOpcode() != ISD::TargetGlobalTLSAddress) { 1289 Base = N.getOperand(0); 1290 if (Base.getOpcode() == ISD::TargetConstantPool) 1291 return false; // We want to select t2LDRpci instead. 1292 } else 1293 Base = N; 1294 OffImm = CurDAG->getTargetConstant(0, SDLoc(N), MVT::i32); 1295 return true; 1296 } 1297 1298 if (ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N.getOperand(1))) { 1299 if (SelectT2AddrModeImm8(N, Base, OffImm)) 1300 // Let t2LDRi8 handle (R - imm8). 1301 return false; 1302 1303 int RHSC = (int)RHS->getZExtValue(); 1304 if (N.getOpcode() == ISD::SUB) 1305 RHSC = -RHSC; 1306 1307 if (RHSC >= 0 && RHSC < 0x1000) { // 12 bits (unsigned) 1308 Base = N.getOperand(0); 1309 if (Base.getOpcode() == ISD::FrameIndex) { 1310 int FI = cast<FrameIndexSDNode>(Base)->getIndex(); 1311 Base = CurDAG->getTargetFrameIndex( 1312 FI, TLI->getPointerTy(CurDAG->getDataLayout())); 1313 } 1314 OffImm = CurDAG->getTargetConstant(RHSC, SDLoc(N), MVT::i32); 1315 return true; 1316 } 1317 } 1318 1319 // Base only. 1320 Base = N; 1321 OffImm = CurDAG->getTargetConstant(0, SDLoc(N), MVT::i32); 1322 return true; 1323 } 1324 1325 template <unsigned Shift> 1326 bool ARMDAGToDAGISel::SelectT2AddrModeImm8(SDValue N, SDValue &Base, 1327 SDValue &OffImm) { 1328 if (N.getOpcode() == ISD::SUB || CurDAG->isBaseWithConstantOffset(N)) { 1329 int RHSC; 1330 if (isScaledConstantInRange(N.getOperand(1), 1 << Shift, -255, 256, RHSC)) { 1331 Base = N.getOperand(0); 1332 if (Base.getOpcode() == ISD::FrameIndex) { 1333 int FI = cast<FrameIndexSDNode>(Base)->getIndex(); 1334 Base = CurDAG->getTargetFrameIndex( 1335 FI, TLI->getPointerTy(CurDAG->getDataLayout())); 1336 } 1337 1338 if (N.getOpcode() == ISD::SUB) 1339 RHSC = -RHSC; 1340 OffImm = 1341 CurDAG->getTargetConstant(RHSC * (1 << Shift), SDLoc(N), MVT::i32); 1342 return true; 1343 } 1344 } 1345 1346 // Base only. 1347 Base = N; 1348 OffImm = CurDAG->getTargetConstant(0, SDLoc(N), MVT::i32); 1349 return true; 1350 } 1351 1352 bool ARMDAGToDAGISel::SelectT2AddrModeImm8(SDValue N, 1353 SDValue &Base, SDValue &OffImm) { 1354 // Match simple R - imm8 operands. 1355 if (N.getOpcode() != ISD::ADD && N.getOpcode() != ISD::SUB && 1356 !CurDAG->isBaseWithConstantOffset(N)) 1357 return false; 1358 1359 if (ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N.getOperand(1))) { 1360 int RHSC = (int)RHS->getSExtValue(); 1361 if (N.getOpcode() == ISD::SUB) 1362 RHSC = -RHSC; 1363 1364 if ((RHSC >= -255) && (RHSC < 0)) { // 8 bits (always negative) 1365 Base = N.getOperand(0); 1366 if (Base.getOpcode() == ISD::FrameIndex) { 1367 int FI = cast<FrameIndexSDNode>(Base)->getIndex(); 1368 Base = CurDAG->getTargetFrameIndex( 1369 FI, TLI->getPointerTy(CurDAG->getDataLayout())); 1370 } 1371 OffImm = CurDAG->getTargetConstant(RHSC, SDLoc(N), MVT::i32); 1372 return true; 1373 } 1374 } 1375 1376 return false; 1377 } 1378 1379 bool ARMDAGToDAGISel::SelectT2AddrModeImm8Offset(SDNode *Op, SDValue N, 1380 SDValue &OffImm){ 1381 unsigned Opcode = Op->getOpcode(); 1382 ISD::MemIndexedMode AM = (Opcode == ISD::LOAD) 1383 ? cast<LoadSDNode>(Op)->getAddressingMode() 1384 : cast<StoreSDNode>(Op)->getAddressingMode(); 1385 int RHSC; 1386 if (isScaledConstantInRange(N, /*Scale=*/1, 0, 0x100, RHSC)) { // 8 bits. 1387 OffImm = ((AM == ISD::PRE_INC) || (AM == ISD::POST_INC)) 1388 ? CurDAG->getTargetConstant(RHSC, SDLoc(N), MVT::i32) 1389 : CurDAG->getTargetConstant(-RHSC, SDLoc(N), MVT::i32); 1390 return true; 1391 } 1392 1393 return false; 1394 } 1395 1396 template <unsigned Shift> 1397 bool ARMDAGToDAGISel::SelectT2AddrModeImm7(SDValue N, SDValue &Base, 1398 SDValue &OffImm) { 1399 if (N.getOpcode() == ISD::SUB || CurDAG->isBaseWithConstantOffset(N)) { 1400 int RHSC; 1401 if (isScaledConstantInRange(N.getOperand(1), 1 << Shift, -0x7f, 0x80, 1402 RHSC)) { 1403 Base = N.getOperand(0); 1404 if (Base.getOpcode() == ISD::FrameIndex) { 1405 int FI = cast<FrameIndexSDNode>(Base)->getIndex(); 1406 Base = CurDAG->getTargetFrameIndex( 1407 FI, TLI->getPointerTy(CurDAG->getDataLayout())); 1408 } 1409 1410 if (N.getOpcode() == ISD::SUB) 1411 RHSC = -RHSC; 1412 OffImm = 1413 CurDAG->getTargetConstant(RHSC * (1 << Shift), SDLoc(N), MVT::i32); 1414 return true; 1415 } 1416 } 1417 1418 // Base only. 1419 Base = N; 1420 OffImm = CurDAG->getTargetConstant(0, SDLoc(N), MVT::i32); 1421 return true; 1422 } 1423 1424 template <unsigned Shift> 1425 bool ARMDAGToDAGISel::SelectT2AddrModeImm7Offset(SDNode *Op, SDValue N, 1426 SDValue &OffImm) { 1427 return SelectT2AddrModeImm7Offset(Op, N, OffImm, Shift); 1428 } 1429 1430 bool ARMDAGToDAGISel::SelectT2AddrModeImm7Offset(SDNode *Op, SDValue N, 1431 SDValue &OffImm, 1432 unsigned Shift) { 1433 unsigned Opcode = Op->getOpcode(); 1434 ISD::MemIndexedMode AM; 1435 switch (Opcode) { 1436 case ISD::LOAD: 1437 AM = cast<LoadSDNode>(Op)->getAddressingMode(); 1438 break; 1439 case ISD::STORE: 1440 AM = cast<StoreSDNode>(Op)->getAddressingMode(); 1441 break; 1442 case ISD::MLOAD: 1443 AM = cast<MaskedLoadSDNode>(Op)->getAddressingMode(); 1444 break; 1445 case ISD::MSTORE: 1446 AM = cast<MaskedStoreSDNode>(Op)->getAddressingMode(); 1447 break; 1448 default: 1449 llvm_unreachable("Unexpected Opcode for Imm7Offset"); 1450 } 1451 1452 int RHSC; 1453 // 7 bit constant, shifted by Shift. 1454 if (isScaledConstantInRange(N, 1 << Shift, 0, 0x80, RHSC)) { 1455 OffImm = 1456 ((AM == ISD::PRE_INC) || (AM == ISD::POST_INC)) 1457 ? CurDAG->getTargetConstant(RHSC * (1 << Shift), SDLoc(N), MVT::i32) 1458 : CurDAG->getTargetConstant(-RHSC * (1 << Shift), SDLoc(N), 1459 MVT::i32); 1460 return true; 1461 } 1462 return false; 1463 } 1464 1465 template <int Min, int Max> 1466 bool ARMDAGToDAGISel::SelectImmediateInRange(SDValue N, SDValue &OffImm) { 1467 int Val; 1468 if (isScaledConstantInRange(N, 1, Min, Max, Val)) { 1469 OffImm = CurDAG->getTargetConstant(Val, SDLoc(N), MVT::i32); 1470 return true; 1471 } 1472 return false; 1473 } 1474 1475 bool ARMDAGToDAGISel::SelectT2AddrModeSoReg(SDValue N, 1476 SDValue &Base, 1477 SDValue &OffReg, SDValue &ShImm) { 1478 // (R - imm8) should be handled by t2LDRi8. The rest are handled by t2LDRi12. 1479 if (N.getOpcode() != ISD::ADD && !CurDAG->isBaseWithConstantOffset(N)) 1480 return false; 1481 1482 // Leave (R + imm12) for t2LDRi12, (R - imm8) for t2LDRi8. 1483 if (ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N.getOperand(1))) { 1484 int RHSC = (int)RHS->getZExtValue(); 1485 if (RHSC >= 0 && RHSC < 0x1000) // 12 bits (unsigned) 1486 return false; 1487 else if (RHSC < 0 && RHSC >= -255) // 8 bits 1488 return false; 1489 } 1490 1491 // Look for (R + R) or (R + (R << [1,2,3])). 1492 unsigned ShAmt = 0; 1493 Base = N.getOperand(0); 1494 OffReg = N.getOperand(1); 1495 1496 // Swap if it is ((R << c) + R). 1497 ARM_AM::ShiftOpc ShOpcVal = ARM_AM::getShiftOpcForNode(OffReg.getOpcode()); 1498 if (ShOpcVal != ARM_AM::lsl) { 1499 ShOpcVal = ARM_AM::getShiftOpcForNode(Base.getOpcode()); 1500 if (ShOpcVal == ARM_AM::lsl) 1501 std::swap(Base, OffReg); 1502 } 1503 1504 if (ShOpcVal == ARM_AM::lsl) { 1505 // Check to see if the RHS of the shift is a constant, if not, we can't fold 1506 // it. 1507 if (ConstantSDNode *Sh = dyn_cast<ConstantSDNode>(OffReg.getOperand(1))) { 1508 ShAmt = Sh->getZExtValue(); 1509 if (ShAmt < 4 && isShifterOpProfitable(OffReg, ShOpcVal, ShAmt)) 1510 OffReg = OffReg.getOperand(0); 1511 else { 1512 ShAmt = 0; 1513 } 1514 } 1515 } 1516 1517 // If OffReg is a multiply-by-constant and it's profitable to extract a shift 1518 // and use it in a shifted operand do so. 1519 if (OffReg.getOpcode() == ISD::MUL && N.hasOneUse()) { 1520 unsigned PowerOfTwo = 0; 1521 SDValue NewMulConst; 1522 if (canExtractShiftFromMul(OffReg, 3, PowerOfTwo, NewMulConst)) { 1523 HandleSDNode Handle(OffReg); 1524 replaceDAGValue(OffReg.getOperand(1), NewMulConst); 1525 OffReg = Handle.getValue(); 1526 ShAmt = PowerOfTwo; 1527 } 1528 } 1529 1530 ShImm = CurDAG->getTargetConstant(ShAmt, SDLoc(N), MVT::i32); 1531 1532 return true; 1533 } 1534 1535 bool ARMDAGToDAGISel::SelectT2AddrModeExclusive(SDValue N, SDValue &Base, 1536 SDValue &OffImm) { 1537 // This *must* succeed since it's used for the irreplaceable ldrex and strex 1538 // instructions. 1539 Base = N; 1540 OffImm = CurDAG->getTargetConstant(0, SDLoc(N), MVT::i32); 1541 1542 if (N.getOpcode() != ISD::ADD || !CurDAG->isBaseWithConstantOffset(N)) 1543 return true; 1544 1545 ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N.getOperand(1)); 1546 if (!RHS) 1547 return true; 1548 1549 uint32_t RHSC = (int)RHS->getZExtValue(); 1550 if (RHSC > 1020 || RHSC % 4 != 0) 1551 return true; 1552 1553 Base = N.getOperand(0); 1554 if (Base.getOpcode() == ISD::FrameIndex) { 1555 int FI = cast<FrameIndexSDNode>(Base)->getIndex(); 1556 Base = CurDAG->getTargetFrameIndex( 1557 FI, TLI->getPointerTy(CurDAG->getDataLayout())); 1558 } 1559 1560 OffImm = CurDAG->getTargetConstant(RHSC/4, SDLoc(N), MVT::i32); 1561 return true; 1562 } 1563 1564 //===--------------------------------------------------------------------===// 1565 1566 /// getAL - Returns a ARMCC::AL immediate node. 1567 static inline SDValue getAL(SelectionDAG *CurDAG, const SDLoc &dl) { 1568 return CurDAG->getTargetConstant((uint64_t)ARMCC::AL, dl, MVT::i32); 1569 } 1570 1571 void ARMDAGToDAGISel::transferMemOperands(SDNode *N, SDNode *Result) { 1572 MachineMemOperand *MemOp = cast<MemSDNode>(N)->getMemOperand(); 1573 CurDAG->setNodeMemRefs(cast<MachineSDNode>(Result), {MemOp}); 1574 } 1575 1576 bool ARMDAGToDAGISel::tryARMIndexedLoad(SDNode *N) { 1577 LoadSDNode *LD = cast<LoadSDNode>(N); 1578 ISD::MemIndexedMode AM = LD->getAddressingMode(); 1579 if (AM == ISD::UNINDEXED) 1580 return false; 1581 1582 EVT LoadedVT = LD->getMemoryVT(); 1583 SDValue Offset, AMOpc; 1584 bool isPre = (AM == ISD::PRE_INC) || (AM == ISD::PRE_DEC); 1585 unsigned Opcode = 0; 1586 bool Match = false; 1587 if (LoadedVT == MVT::i32 && isPre && 1588 SelectAddrMode2OffsetImmPre(N, LD->getOffset(), Offset, AMOpc)) { 1589 Opcode = ARM::LDR_PRE_IMM; 1590 Match = true; 1591 } else if (LoadedVT == MVT::i32 && !isPre && 1592 SelectAddrMode2OffsetImm(N, LD->getOffset(), Offset, AMOpc)) { 1593 Opcode = ARM::LDR_POST_IMM; 1594 Match = true; 1595 } else if (LoadedVT == MVT::i32 && 1596 SelectAddrMode2OffsetReg(N, LD->getOffset(), Offset, AMOpc)) { 1597 Opcode = isPre ? ARM::LDR_PRE_REG : ARM::LDR_POST_REG; 1598 Match = true; 1599 1600 } else if (LoadedVT == MVT::i16 && 1601 SelectAddrMode3Offset(N, LD->getOffset(), Offset, AMOpc)) { 1602 Match = true; 1603 Opcode = (LD->getExtensionType() == ISD::SEXTLOAD) 1604 ? (isPre ? ARM::LDRSH_PRE : ARM::LDRSH_POST) 1605 : (isPre ? ARM::LDRH_PRE : ARM::LDRH_POST); 1606 } else if (LoadedVT == MVT::i8 || LoadedVT == MVT::i1) { 1607 if (LD->getExtensionType() == ISD::SEXTLOAD) { 1608 if (SelectAddrMode3Offset(N, LD->getOffset(), Offset, AMOpc)) { 1609 Match = true; 1610 Opcode = isPre ? ARM::LDRSB_PRE : ARM::LDRSB_POST; 1611 } 1612 } else { 1613 if (isPre && 1614 SelectAddrMode2OffsetImmPre(N, LD->getOffset(), Offset, AMOpc)) { 1615 Match = true; 1616 Opcode = ARM::LDRB_PRE_IMM; 1617 } else if (!isPre && 1618 SelectAddrMode2OffsetImm(N, LD->getOffset(), Offset, AMOpc)) { 1619 Match = true; 1620 Opcode = ARM::LDRB_POST_IMM; 1621 } else if (SelectAddrMode2OffsetReg(N, LD->getOffset(), Offset, AMOpc)) { 1622 Match = true; 1623 Opcode = isPre ? ARM::LDRB_PRE_REG : ARM::LDRB_POST_REG; 1624 } 1625 } 1626 } 1627 1628 if (Match) { 1629 if (Opcode == ARM::LDR_PRE_IMM || Opcode == ARM::LDRB_PRE_IMM) { 1630 SDValue Chain = LD->getChain(); 1631 SDValue Base = LD->getBasePtr(); 1632 SDValue Ops[]= { Base, AMOpc, getAL(CurDAG, SDLoc(N)), 1633 CurDAG->getRegister(0, MVT::i32), Chain }; 1634 SDNode *New = CurDAG->getMachineNode(Opcode, SDLoc(N), MVT::i32, MVT::i32, 1635 MVT::Other, Ops); 1636 transferMemOperands(N, New); 1637 ReplaceNode(N, New); 1638 return true; 1639 } else { 1640 SDValue Chain = LD->getChain(); 1641 SDValue Base = LD->getBasePtr(); 1642 SDValue Ops[]= { Base, Offset, AMOpc, getAL(CurDAG, SDLoc(N)), 1643 CurDAG->getRegister(0, MVT::i32), Chain }; 1644 SDNode *New = CurDAG->getMachineNode(Opcode, SDLoc(N), MVT::i32, MVT::i32, 1645 MVT::Other, Ops); 1646 transferMemOperands(N, New); 1647 ReplaceNode(N, New); 1648 return true; 1649 } 1650 } 1651 1652 return false; 1653 } 1654 1655 bool ARMDAGToDAGISel::tryT1IndexedLoad(SDNode *N) { 1656 LoadSDNode *LD = cast<LoadSDNode>(N); 1657 EVT LoadedVT = LD->getMemoryVT(); 1658 ISD::MemIndexedMode AM = LD->getAddressingMode(); 1659 if (AM != ISD::POST_INC || LD->getExtensionType() != ISD::NON_EXTLOAD || 1660 LoadedVT.getSimpleVT().SimpleTy != MVT::i32) 1661 return false; 1662 1663 auto *COffs = dyn_cast<ConstantSDNode>(LD->getOffset()); 1664 if (!COffs || COffs->getZExtValue() != 4) 1665 return false; 1666 1667 // A T1 post-indexed load is just a single register LDM: LDM r0!, {r1}. 1668 // The encoding of LDM is not how the rest of ISel expects a post-inc load to 1669 // look however, so we use a pseudo here and switch it for a tLDMIA_UPD after 1670 // ISel. 1671 SDValue Chain = LD->getChain(); 1672 SDValue Base = LD->getBasePtr(); 1673 SDValue Ops[]= { Base, getAL(CurDAG, SDLoc(N)), 1674 CurDAG->getRegister(0, MVT::i32), Chain }; 1675 SDNode *New = CurDAG->getMachineNode(ARM::tLDR_postidx, SDLoc(N), MVT::i32, 1676 MVT::i32, MVT::Other, Ops); 1677 transferMemOperands(N, New); 1678 ReplaceNode(N, New); 1679 return true; 1680 } 1681 1682 bool ARMDAGToDAGISel::tryT2IndexedLoad(SDNode *N) { 1683 LoadSDNode *LD = cast<LoadSDNode>(N); 1684 ISD::MemIndexedMode AM = LD->getAddressingMode(); 1685 if (AM == ISD::UNINDEXED) 1686 return false; 1687 1688 EVT LoadedVT = LD->getMemoryVT(); 1689 bool isSExtLd = LD->getExtensionType() == ISD::SEXTLOAD; 1690 SDValue Offset; 1691 bool isPre = (AM == ISD::PRE_INC) || (AM == ISD::PRE_DEC); 1692 unsigned Opcode = 0; 1693 bool Match = false; 1694 if (SelectT2AddrModeImm8Offset(N, LD->getOffset(), Offset)) { 1695 switch (LoadedVT.getSimpleVT().SimpleTy) { 1696 case MVT::i32: 1697 Opcode = isPre ? ARM::t2LDR_PRE : ARM::t2LDR_POST; 1698 break; 1699 case MVT::i16: 1700 if (isSExtLd) 1701 Opcode = isPre ? ARM::t2LDRSH_PRE : ARM::t2LDRSH_POST; 1702 else 1703 Opcode = isPre ? ARM::t2LDRH_PRE : ARM::t2LDRH_POST; 1704 break; 1705 case MVT::i8: 1706 case MVT::i1: 1707 if (isSExtLd) 1708 Opcode = isPre ? ARM::t2LDRSB_PRE : ARM::t2LDRSB_POST; 1709 else 1710 Opcode = isPre ? ARM::t2LDRB_PRE : ARM::t2LDRB_POST; 1711 break; 1712 default: 1713 return false; 1714 } 1715 Match = true; 1716 } 1717 1718 if (Match) { 1719 SDValue Chain = LD->getChain(); 1720 SDValue Base = LD->getBasePtr(); 1721 SDValue Ops[]= { Base, Offset, getAL(CurDAG, SDLoc(N)), 1722 CurDAG->getRegister(0, MVT::i32), Chain }; 1723 SDNode *New = CurDAG->getMachineNode(Opcode, SDLoc(N), MVT::i32, MVT::i32, 1724 MVT::Other, Ops); 1725 transferMemOperands(N, New); 1726 ReplaceNode(N, New); 1727 return true; 1728 } 1729 1730 return false; 1731 } 1732 1733 bool ARMDAGToDAGISel::tryMVEIndexedLoad(SDNode *N) { 1734 EVT LoadedVT; 1735 unsigned Opcode = 0; 1736 bool isSExtLd, isPre; 1737 Align Alignment; 1738 ARMVCC::VPTCodes Pred; 1739 SDValue PredReg; 1740 SDValue Chain, Base, Offset; 1741 1742 if (LoadSDNode *LD = dyn_cast<LoadSDNode>(N)) { 1743 ISD::MemIndexedMode AM = LD->getAddressingMode(); 1744 if (AM == ISD::UNINDEXED) 1745 return false; 1746 LoadedVT = LD->getMemoryVT(); 1747 if (!LoadedVT.isVector()) 1748 return false; 1749 1750 Chain = LD->getChain(); 1751 Base = LD->getBasePtr(); 1752 Offset = LD->getOffset(); 1753 Alignment = LD->getAlign(); 1754 isSExtLd = LD->getExtensionType() == ISD::SEXTLOAD; 1755 isPre = (AM == ISD::PRE_INC) || (AM == ISD::PRE_DEC); 1756 Pred = ARMVCC::None; 1757 PredReg = CurDAG->getRegister(0, MVT::i32); 1758 } else if (MaskedLoadSDNode *LD = dyn_cast<MaskedLoadSDNode>(N)) { 1759 ISD::MemIndexedMode AM = LD->getAddressingMode(); 1760 if (AM == ISD::UNINDEXED) 1761 return false; 1762 LoadedVT = LD->getMemoryVT(); 1763 if (!LoadedVT.isVector()) 1764 return false; 1765 1766 Chain = LD->getChain(); 1767 Base = LD->getBasePtr(); 1768 Offset = LD->getOffset(); 1769 Alignment = LD->getAlign(); 1770 isSExtLd = LD->getExtensionType() == ISD::SEXTLOAD; 1771 isPre = (AM == ISD::PRE_INC) || (AM == ISD::PRE_DEC); 1772 Pred = ARMVCC::Then; 1773 PredReg = LD->getMask(); 1774 } else 1775 llvm_unreachable("Expected a Load or a Masked Load!"); 1776 1777 // We allow LE non-masked loads to change the type (for example use a vldrb.8 1778 // as opposed to a vldrw.32). This can allow extra addressing modes or 1779 // alignments for what is otherwise an equivalent instruction. 1780 bool CanChangeType = Subtarget->isLittle() && !isa<MaskedLoadSDNode>(N); 1781 1782 SDValue NewOffset; 1783 if (Alignment >= Align(2) && LoadedVT == MVT::v4i16 && 1784 SelectT2AddrModeImm7Offset(N, Offset, NewOffset, 1)) { 1785 if (isSExtLd) 1786 Opcode = isPre ? ARM::MVE_VLDRHS32_pre : ARM::MVE_VLDRHS32_post; 1787 else 1788 Opcode = isPre ? ARM::MVE_VLDRHU32_pre : ARM::MVE_VLDRHU32_post; 1789 } else if (LoadedVT == MVT::v8i8 && 1790 SelectT2AddrModeImm7Offset(N, Offset, NewOffset, 0)) { 1791 if (isSExtLd) 1792 Opcode = isPre ? ARM::MVE_VLDRBS16_pre : ARM::MVE_VLDRBS16_post; 1793 else 1794 Opcode = isPre ? ARM::MVE_VLDRBU16_pre : ARM::MVE_VLDRBU16_post; 1795 } else if (LoadedVT == MVT::v4i8 && 1796 SelectT2AddrModeImm7Offset(N, Offset, NewOffset, 0)) { 1797 if (isSExtLd) 1798 Opcode = isPre ? ARM::MVE_VLDRBS32_pre : ARM::MVE_VLDRBS32_post; 1799 else 1800 Opcode = isPre ? ARM::MVE_VLDRBU32_pre : ARM::MVE_VLDRBU32_post; 1801 } else if (Alignment >= Align(4) && 1802 (CanChangeType || LoadedVT == MVT::v4i32 || 1803 LoadedVT == MVT::v4f32) && 1804 SelectT2AddrModeImm7Offset(N, Offset, NewOffset, 2)) 1805 Opcode = isPre ? ARM::MVE_VLDRWU32_pre : ARM::MVE_VLDRWU32_post; 1806 else if (Alignment >= Align(2) && 1807 (CanChangeType || LoadedVT == MVT::v8i16 || 1808 LoadedVT == MVT::v8f16) && 1809 SelectT2AddrModeImm7Offset(N, Offset, NewOffset, 1)) 1810 Opcode = isPre ? ARM::MVE_VLDRHU16_pre : ARM::MVE_VLDRHU16_post; 1811 else if ((CanChangeType || LoadedVT == MVT::v16i8) && 1812 SelectT2AddrModeImm7Offset(N, Offset, NewOffset, 0)) 1813 Opcode = isPre ? ARM::MVE_VLDRBU8_pre : ARM::MVE_VLDRBU8_post; 1814 else 1815 return false; 1816 1817 SDValue Ops[] = {Base, NewOffset, 1818 CurDAG->getTargetConstant(Pred, SDLoc(N), MVT::i32), PredReg, 1819 Chain}; 1820 SDNode *New = CurDAG->getMachineNode(Opcode, SDLoc(N), MVT::i32, 1821 N->getValueType(0), MVT::Other, Ops); 1822 transferMemOperands(N, New); 1823 ReplaceUses(SDValue(N, 0), SDValue(New, 1)); 1824 ReplaceUses(SDValue(N, 1), SDValue(New, 0)); 1825 ReplaceUses(SDValue(N, 2), SDValue(New, 2)); 1826 CurDAG->RemoveDeadNode(N); 1827 return true; 1828 } 1829 1830 /// Form a GPRPair pseudo register from a pair of GPR regs. 1831 SDNode *ARMDAGToDAGISel::createGPRPairNode(EVT VT, SDValue V0, SDValue V1) { 1832 SDLoc dl(V0.getNode()); 1833 SDValue RegClass = 1834 CurDAG->getTargetConstant(ARM::GPRPairRegClassID, dl, MVT::i32); 1835 SDValue SubReg0 = CurDAG->getTargetConstant(ARM::gsub_0, dl, MVT::i32); 1836 SDValue SubReg1 = CurDAG->getTargetConstant(ARM::gsub_1, dl, MVT::i32); 1837 const SDValue Ops[] = { RegClass, V0, SubReg0, V1, SubReg1 }; 1838 return CurDAG->getMachineNode(TargetOpcode::REG_SEQUENCE, dl, VT, Ops); 1839 } 1840 1841 /// Form a D register from a pair of S registers. 1842 SDNode *ARMDAGToDAGISel::createSRegPairNode(EVT VT, SDValue V0, SDValue V1) { 1843 SDLoc dl(V0.getNode()); 1844 SDValue RegClass = 1845 CurDAG->getTargetConstant(ARM::DPR_VFP2RegClassID, dl, MVT::i32); 1846 SDValue SubReg0 = CurDAG->getTargetConstant(ARM::ssub_0, dl, MVT::i32); 1847 SDValue SubReg1 = CurDAG->getTargetConstant(ARM::ssub_1, dl, MVT::i32); 1848 const SDValue Ops[] = { RegClass, V0, SubReg0, V1, SubReg1 }; 1849 return CurDAG->getMachineNode(TargetOpcode::REG_SEQUENCE, dl, VT, Ops); 1850 } 1851 1852 /// Form a quad register from a pair of D registers. 1853 SDNode *ARMDAGToDAGISel::createDRegPairNode(EVT VT, SDValue V0, SDValue V1) { 1854 SDLoc dl(V0.getNode()); 1855 SDValue RegClass = CurDAG->getTargetConstant(ARM::QPRRegClassID, dl, 1856 MVT::i32); 1857 SDValue SubReg0 = CurDAG->getTargetConstant(ARM::dsub_0, dl, MVT::i32); 1858 SDValue SubReg1 = CurDAG->getTargetConstant(ARM::dsub_1, dl, MVT::i32); 1859 const SDValue Ops[] = { RegClass, V0, SubReg0, V1, SubReg1 }; 1860 return CurDAG->getMachineNode(TargetOpcode::REG_SEQUENCE, dl, VT, Ops); 1861 } 1862 1863 /// Form 4 consecutive D registers from a pair of Q registers. 1864 SDNode *ARMDAGToDAGISel::createQRegPairNode(EVT VT, SDValue V0, SDValue V1) { 1865 SDLoc dl(V0.getNode()); 1866 SDValue RegClass = CurDAG->getTargetConstant(ARM::QQPRRegClassID, dl, 1867 MVT::i32); 1868 SDValue SubReg0 = CurDAG->getTargetConstant(ARM::qsub_0, dl, MVT::i32); 1869 SDValue SubReg1 = CurDAG->getTargetConstant(ARM::qsub_1, dl, MVT::i32); 1870 const SDValue Ops[] = { RegClass, V0, SubReg0, V1, SubReg1 }; 1871 return CurDAG->getMachineNode(TargetOpcode::REG_SEQUENCE, dl, VT, Ops); 1872 } 1873 1874 /// Form 4 consecutive S registers. 1875 SDNode *ARMDAGToDAGISel::createQuadSRegsNode(EVT VT, SDValue V0, SDValue V1, 1876 SDValue V2, SDValue V3) { 1877 SDLoc dl(V0.getNode()); 1878 SDValue RegClass = 1879 CurDAG->getTargetConstant(ARM::QPR_VFP2RegClassID, dl, MVT::i32); 1880 SDValue SubReg0 = CurDAG->getTargetConstant(ARM::ssub_0, dl, MVT::i32); 1881 SDValue SubReg1 = CurDAG->getTargetConstant(ARM::ssub_1, dl, MVT::i32); 1882 SDValue SubReg2 = CurDAG->getTargetConstant(ARM::ssub_2, dl, MVT::i32); 1883 SDValue SubReg3 = CurDAG->getTargetConstant(ARM::ssub_3, dl, MVT::i32); 1884 const SDValue Ops[] = { RegClass, V0, SubReg0, V1, SubReg1, 1885 V2, SubReg2, V3, SubReg3 }; 1886 return CurDAG->getMachineNode(TargetOpcode::REG_SEQUENCE, dl, VT, Ops); 1887 } 1888 1889 /// Form 4 consecutive D registers. 1890 SDNode *ARMDAGToDAGISel::createQuadDRegsNode(EVT VT, SDValue V0, SDValue V1, 1891 SDValue V2, SDValue V3) { 1892 SDLoc dl(V0.getNode()); 1893 SDValue RegClass = CurDAG->getTargetConstant(ARM::QQPRRegClassID, dl, 1894 MVT::i32); 1895 SDValue SubReg0 = CurDAG->getTargetConstant(ARM::dsub_0, dl, MVT::i32); 1896 SDValue SubReg1 = CurDAG->getTargetConstant(ARM::dsub_1, dl, MVT::i32); 1897 SDValue SubReg2 = CurDAG->getTargetConstant(ARM::dsub_2, dl, MVT::i32); 1898 SDValue SubReg3 = CurDAG->getTargetConstant(ARM::dsub_3, dl, MVT::i32); 1899 const SDValue Ops[] = { RegClass, V0, SubReg0, V1, SubReg1, 1900 V2, SubReg2, V3, SubReg3 }; 1901 return CurDAG->getMachineNode(TargetOpcode::REG_SEQUENCE, dl, VT, Ops); 1902 } 1903 1904 /// Form 4 consecutive Q registers. 1905 SDNode *ARMDAGToDAGISel::createQuadQRegsNode(EVT VT, SDValue V0, SDValue V1, 1906 SDValue V2, SDValue V3) { 1907 SDLoc dl(V0.getNode()); 1908 SDValue RegClass = CurDAG->getTargetConstant(ARM::QQQQPRRegClassID, dl, 1909 MVT::i32); 1910 SDValue SubReg0 = CurDAG->getTargetConstant(ARM::qsub_0, dl, MVT::i32); 1911 SDValue SubReg1 = CurDAG->getTargetConstant(ARM::qsub_1, dl, MVT::i32); 1912 SDValue SubReg2 = CurDAG->getTargetConstant(ARM::qsub_2, dl, MVT::i32); 1913 SDValue SubReg3 = CurDAG->getTargetConstant(ARM::qsub_3, dl, MVT::i32); 1914 const SDValue Ops[] = { RegClass, V0, SubReg0, V1, SubReg1, 1915 V2, SubReg2, V3, SubReg3 }; 1916 return CurDAG->getMachineNode(TargetOpcode::REG_SEQUENCE, dl, VT, Ops); 1917 } 1918 1919 /// GetVLDSTAlign - Get the alignment (in bytes) for the alignment operand 1920 /// of a NEON VLD or VST instruction. The supported values depend on the 1921 /// number of registers being loaded. 1922 SDValue ARMDAGToDAGISel::GetVLDSTAlign(SDValue Align, const SDLoc &dl, 1923 unsigned NumVecs, bool is64BitVector) { 1924 unsigned NumRegs = NumVecs; 1925 if (!is64BitVector && NumVecs < 3) 1926 NumRegs *= 2; 1927 1928 unsigned Alignment = cast<ConstantSDNode>(Align)->getZExtValue(); 1929 if (Alignment >= 32 && NumRegs == 4) 1930 Alignment = 32; 1931 else if (Alignment >= 16 && (NumRegs == 2 || NumRegs == 4)) 1932 Alignment = 16; 1933 else if (Alignment >= 8) 1934 Alignment = 8; 1935 else 1936 Alignment = 0; 1937 1938 return CurDAG->getTargetConstant(Alignment, dl, MVT::i32); 1939 } 1940 1941 static bool isVLDfixed(unsigned Opc) 1942 { 1943 switch (Opc) { 1944 default: return false; 1945 case ARM::VLD1d8wb_fixed : return true; 1946 case ARM::VLD1d16wb_fixed : return true; 1947 case ARM::VLD1d64Qwb_fixed : return true; 1948 case ARM::VLD1d32wb_fixed : return true; 1949 case ARM::VLD1d64wb_fixed : return true; 1950 case ARM::VLD1d8TPseudoWB_fixed : return true; 1951 case ARM::VLD1d16TPseudoWB_fixed : return true; 1952 case ARM::VLD1d32TPseudoWB_fixed : return true; 1953 case ARM::VLD1d64TPseudoWB_fixed : return true; 1954 case ARM::VLD1d8QPseudoWB_fixed : return true; 1955 case ARM::VLD1d16QPseudoWB_fixed : return true; 1956 case ARM::VLD1d32QPseudoWB_fixed : return true; 1957 case ARM::VLD1d64QPseudoWB_fixed : return true; 1958 case ARM::VLD1q8wb_fixed : return true; 1959 case ARM::VLD1q16wb_fixed : return true; 1960 case ARM::VLD1q32wb_fixed : return true; 1961 case ARM::VLD1q64wb_fixed : return true; 1962 case ARM::VLD1DUPd8wb_fixed : return true; 1963 case ARM::VLD1DUPd16wb_fixed : return true; 1964 case ARM::VLD1DUPd32wb_fixed : return true; 1965 case ARM::VLD1DUPq8wb_fixed : return true; 1966 case ARM::VLD1DUPq16wb_fixed : return true; 1967 case ARM::VLD1DUPq32wb_fixed : return true; 1968 case ARM::VLD2d8wb_fixed : return true; 1969 case ARM::VLD2d16wb_fixed : return true; 1970 case ARM::VLD2d32wb_fixed : return true; 1971 case ARM::VLD2q8PseudoWB_fixed : return true; 1972 case ARM::VLD2q16PseudoWB_fixed : return true; 1973 case ARM::VLD2q32PseudoWB_fixed : return true; 1974 case ARM::VLD2DUPd8wb_fixed : return true; 1975 case ARM::VLD2DUPd16wb_fixed : return true; 1976 case ARM::VLD2DUPd32wb_fixed : return true; 1977 case ARM::VLD2DUPq8OddPseudoWB_fixed: return true; 1978 case ARM::VLD2DUPq16OddPseudoWB_fixed: return true; 1979 case ARM::VLD2DUPq32OddPseudoWB_fixed: return true; 1980 } 1981 } 1982 1983 static bool isVSTfixed(unsigned Opc) 1984 { 1985 switch (Opc) { 1986 default: return false; 1987 case ARM::VST1d8wb_fixed : return true; 1988 case ARM::VST1d16wb_fixed : return true; 1989 case ARM::VST1d32wb_fixed : return true; 1990 case ARM::VST1d64wb_fixed : return true; 1991 case ARM::VST1q8wb_fixed : return true; 1992 case ARM::VST1q16wb_fixed : return true; 1993 case ARM::VST1q32wb_fixed : return true; 1994 case ARM::VST1q64wb_fixed : return true; 1995 case ARM::VST1d8TPseudoWB_fixed : return true; 1996 case ARM::VST1d16TPseudoWB_fixed : return true; 1997 case ARM::VST1d32TPseudoWB_fixed : return true; 1998 case ARM::VST1d64TPseudoWB_fixed : return true; 1999 case ARM::VST1d8QPseudoWB_fixed : return true; 2000 case ARM::VST1d16QPseudoWB_fixed : return true; 2001 case ARM::VST1d32QPseudoWB_fixed : return true; 2002 case ARM::VST1d64QPseudoWB_fixed : return true; 2003 case ARM::VST2d8wb_fixed : return true; 2004 case ARM::VST2d16wb_fixed : return true; 2005 case ARM::VST2d32wb_fixed : return true; 2006 case ARM::VST2q8PseudoWB_fixed : return true; 2007 case ARM::VST2q16PseudoWB_fixed : return true; 2008 case ARM::VST2q32PseudoWB_fixed : return true; 2009 } 2010 } 2011 2012 // Get the register stride update opcode of a VLD/VST instruction that 2013 // is otherwise equivalent to the given fixed stride updating instruction. 2014 static unsigned getVLDSTRegisterUpdateOpcode(unsigned Opc) { 2015 assert((isVLDfixed(Opc) || isVSTfixed(Opc)) 2016 && "Incorrect fixed stride updating instruction."); 2017 switch (Opc) { 2018 default: break; 2019 case ARM::VLD1d8wb_fixed: return ARM::VLD1d8wb_register; 2020 case ARM::VLD1d16wb_fixed: return ARM::VLD1d16wb_register; 2021 case ARM::VLD1d32wb_fixed: return ARM::VLD1d32wb_register; 2022 case ARM::VLD1d64wb_fixed: return ARM::VLD1d64wb_register; 2023 case ARM::VLD1q8wb_fixed: return ARM::VLD1q8wb_register; 2024 case ARM::VLD1q16wb_fixed: return ARM::VLD1q16wb_register; 2025 case ARM::VLD1q32wb_fixed: return ARM::VLD1q32wb_register; 2026 case ARM::VLD1q64wb_fixed: return ARM::VLD1q64wb_register; 2027 case ARM::VLD1d64Twb_fixed: return ARM::VLD1d64Twb_register; 2028 case ARM::VLD1d64Qwb_fixed: return ARM::VLD1d64Qwb_register; 2029 case ARM::VLD1d8TPseudoWB_fixed: return ARM::VLD1d8TPseudoWB_register; 2030 case ARM::VLD1d16TPseudoWB_fixed: return ARM::VLD1d16TPseudoWB_register; 2031 case ARM::VLD1d32TPseudoWB_fixed: return ARM::VLD1d32TPseudoWB_register; 2032 case ARM::VLD1d64TPseudoWB_fixed: return ARM::VLD1d64TPseudoWB_register; 2033 case ARM::VLD1d8QPseudoWB_fixed: return ARM::VLD1d8QPseudoWB_register; 2034 case ARM::VLD1d16QPseudoWB_fixed: return ARM::VLD1d16QPseudoWB_register; 2035 case ARM::VLD1d32QPseudoWB_fixed: return ARM::VLD1d32QPseudoWB_register; 2036 case ARM::VLD1d64QPseudoWB_fixed: return ARM::VLD1d64QPseudoWB_register; 2037 case ARM::VLD1DUPd8wb_fixed : return ARM::VLD1DUPd8wb_register; 2038 case ARM::VLD1DUPd16wb_fixed : return ARM::VLD1DUPd16wb_register; 2039 case ARM::VLD1DUPd32wb_fixed : return ARM::VLD1DUPd32wb_register; 2040 case ARM::VLD1DUPq8wb_fixed : return ARM::VLD1DUPq8wb_register; 2041 case ARM::VLD1DUPq16wb_fixed : return ARM::VLD1DUPq16wb_register; 2042 case ARM::VLD1DUPq32wb_fixed : return ARM::VLD1DUPq32wb_register; 2043 case ARM::VLD2DUPq8OddPseudoWB_fixed: return ARM::VLD2DUPq8OddPseudoWB_register; 2044 case ARM::VLD2DUPq16OddPseudoWB_fixed: return ARM::VLD2DUPq16OddPseudoWB_register; 2045 case ARM::VLD2DUPq32OddPseudoWB_fixed: return ARM::VLD2DUPq32OddPseudoWB_register; 2046 2047 case ARM::VST1d8wb_fixed: return ARM::VST1d8wb_register; 2048 case ARM::VST1d16wb_fixed: return ARM::VST1d16wb_register; 2049 case ARM::VST1d32wb_fixed: return ARM::VST1d32wb_register; 2050 case ARM::VST1d64wb_fixed: return ARM::VST1d64wb_register; 2051 case ARM::VST1q8wb_fixed: return ARM::VST1q8wb_register; 2052 case ARM::VST1q16wb_fixed: return ARM::VST1q16wb_register; 2053 case ARM::VST1q32wb_fixed: return ARM::VST1q32wb_register; 2054 case ARM::VST1q64wb_fixed: return ARM::VST1q64wb_register; 2055 case ARM::VST1d8TPseudoWB_fixed: return ARM::VST1d8TPseudoWB_register; 2056 case ARM::VST1d16TPseudoWB_fixed: return ARM::VST1d16TPseudoWB_register; 2057 case ARM::VST1d32TPseudoWB_fixed: return ARM::VST1d32TPseudoWB_register; 2058 case ARM::VST1d64TPseudoWB_fixed: return ARM::VST1d64TPseudoWB_register; 2059 case ARM::VST1d8QPseudoWB_fixed: return ARM::VST1d8QPseudoWB_register; 2060 case ARM::VST1d16QPseudoWB_fixed: return ARM::VST1d16QPseudoWB_register; 2061 case ARM::VST1d32QPseudoWB_fixed: return ARM::VST1d32QPseudoWB_register; 2062 case ARM::VST1d64QPseudoWB_fixed: return ARM::VST1d64QPseudoWB_register; 2063 2064 case ARM::VLD2d8wb_fixed: return ARM::VLD2d8wb_register; 2065 case ARM::VLD2d16wb_fixed: return ARM::VLD2d16wb_register; 2066 case ARM::VLD2d32wb_fixed: return ARM::VLD2d32wb_register; 2067 case ARM::VLD2q8PseudoWB_fixed: return ARM::VLD2q8PseudoWB_register; 2068 case ARM::VLD2q16PseudoWB_fixed: return ARM::VLD2q16PseudoWB_register; 2069 case ARM::VLD2q32PseudoWB_fixed: return ARM::VLD2q32PseudoWB_register; 2070 2071 case ARM::VST2d8wb_fixed: return ARM::VST2d8wb_register; 2072 case ARM::VST2d16wb_fixed: return ARM::VST2d16wb_register; 2073 case ARM::VST2d32wb_fixed: return ARM::VST2d32wb_register; 2074 case ARM::VST2q8PseudoWB_fixed: return ARM::VST2q8PseudoWB_register; 2075 case ARM::VST2q16PseudoWB_fixed: return ARM::VST2q16PseudoWB_register; 2076 case ARM::VST2q32PseudoWB_fixed: return ARM::VST2q32PseudoWB_register; 2077 2078 case ARM::VLD2DUPd8wb_fixed: return ARM::VLD2DUPd8wb_register; 2079 case ARM::VLD2DUPd16wb_fixed: return ARM::VLD2DUPd16wb_register; 2080 case ARM::VLD2DUPd32wb_fixed: return ARM::VLD2DUPd32wb_register; 2081 } 2082 return Opc; // If not one we handle, return it unchanged. 2083 } 2084 2085 /// Returns true if the given increment is a Constant known to be equal to the 2086 /// access size performed by a NEON load/store. This means the "[rN]!" form can 2087 /// be used. 2088 static bool isPerfectIncrement(SDValue Inc, EVT VecTy, unsigned NumVecs) { 2089 auto C = dyn_cast<ConstantSDNode>(Inc); 2090 return C && C->getZExtValue() == VecTy.getSizeInBits() / 8 * NumVecs; 2091 } 2092 2093 void ARMDAGToDAGISel::SelectVLD(SDNode *N, bool isUpdating, unsigned NumVecs, 2094 const uint16_t *DOpcodes, 2095 const uint16_t *QOpcodes0, 2096 const uint16_t *QOpcodes1) { 2097 assert(Subtarget->hasNEON()); 2098 assert(NumVecs >= 1 && NumVecs <= 4 && "VLD NumVecs out-of-range"); 2099 SDLoc dl(N); 2100 2101 SDValue MemAddr, Align; 2102 bool IsIntrinsic = !isUpdating; // By coincidence, all supported updating 2103 // nodes are not intrinsics. 2104 unsigned AddrOpIdx = IsIntrinsic ? 2 : 1; 2105 if (!SelectAddrMode6(N, N->getOperand(AddrOpIdx), MemAddr, Align)) 2106 return; 2107 2108 SDValue Chain = N->getOperand(0); 2109 EVT VT = N->getValueType(0); 2110 bool is64BitVector = VT.is64BitVector(); 2111 Align = GetVLDSTAlign(Align, dl, NumVecs, is64BitVector); 2112 2113 unsigned OpcodeIndex; 2114 switch (VT.getSimpleVT().SimpleTy) { 2115 default: llvm_unreachable("unhandled vld type"); 2116 // Double-register operations: 2117 case MVT::v8i8: OpcodeIndex = 0; break; 2118 case MVT::v4f16: 2119 case MVT::v4bf16: 2120 case MVT::v4i16: OpcodeIndex = 1; break; 2121 case MVT::v2f32: 2122 case MVT::v2i32: OpcodeIndex = 2; break; 2123 case MVT::v1i64: OpcodeIndex = 3; break; 2124 // Quad-register operations: 2125 case MVT::v16i8: OpcodeIndex = 0; break; 2126 case MVT::v8f16: 2127 case MVT::v8bf16: 2128 case MVT::v8i16: OpcodeIndex = 1; break; 2129 case MVT::v4f32: 2130 case MVT::v4i32: OpcodeIndex = 2; break; 2131 case MVT::v2f64: 2132 case MVT::v2i64: OpcodeIndex = 3; break; 2133 } 2134 2135 EVT ResTy; 2136 if (NumVecs == 1) 2137 ResTy = VT; 2138 else { 2139 unsigned ResTyElts = (NumVecs == 3) ? 4 : NumVecs; 2140 if (!is64BitVector) 2141 ResTyElts *= 2; 2142 ResTy = EVT::getVectorVT(*CurDAG->getContext(), MVT::i64, ResTyElts); 2143 } 2144 std::vector<EVT> ResTys; 2145 ResTys.push_back(ResTy); 2146 if (isUpdating) 2147 ResTys.push_back(MVT::i32); 2148 ResTys.push_back(MVT::Other); 2149 2150 SDValue Pred = getAL(CurDAG, dl); 2151 SDValue Reg0 = CurDAG->getRegister(0, MVT::i32); 2152 SDNode *VLd; 2153 SmallVector<SDValue, 7> Ops; 2154 2155 // Double registers and VLD1/VLD2 quad registers are directly supported. 2156 if (is64BitVector || NumVecs <= 2) { 2157 unsigned Opc = (is64BitVector ? DOpcodes[OpcodeIndex] : 2158 QOpcodes0[OpcodeIndex]); 2159 Ops.push_back(MemAddr); 2160 Ops.push_back(Align); 2161 if (isUpdating) { 2162 SDValue Inc = N->getOperand(AddrOpIdx + 1); 2163 bool IsImmUpdate = isPerfectIncrement(Inc, VT, NumVecs); 2164 if (!IsImmUpdate) { 2165 // We use a VLD1 for v1i64 even if the pseudo says vld2/3/4, so 2166 // check for the opcode rather than the number of vector elements. 2167 if (isVLDfixed(Opc)) 2168 Opc = getVLDSTRegisterUpdateOpcode(Opc); 2169 Ops.push_back(Inc); 2170 // VLD1/VLD2 fixed increment does not need Reg0 so only include it in 2171 // the operands if not such an opcode. 2172 } else if (!isVLDfixed(Opc)) 2173 Ops.push_back(Reg0); 2174 } 2175 Ops.push_back(Pred); 2176 Ops.push_back(Reg0); 2177 Ops.push_back(Chain); 2178 VLd = CurDAG->getMachineNode(Opc, dl, ResTys, Ops); 2179 2180 } else { 2181 // Otherwise, quad registers are loaded with two separate instructions, 2182 // where one loads the even registers and the other loads the odd registers. 2183 EVT AddrTy = MemAddr.getValueType(); 2184 2185 // Load the even subregs. This is always an updating load, so that it 2186 // provides the address to the second load for the odd subregs. 2187 SDValue ImplDef = 2188 SDValue(CurDAG->getMachineNode(TargetOpcode::IMPLICIT_DEF, dl, ResTy), 0); 2189 const SDValue OpsA[] = { MemAddr, Align, Reg0, ImplDef, Pred, Reg0, Chain }; 2190 SDNode *VLdA = CurDAG->getMachineNode(QOpcodes0[OpcodeIndex], dl, 2191 ResTy, AddrTy, MVT::Other, OpsA); 2192 Chain = SDValue(VLdA, 2); 2193 2194 // Load the odd subregs. 2195 Ops.push_back(SDValue(VLdA, 1)); 2196 Ops.push_back(Align); 2197 if (isUpdating) { 2198 SDValue Inc = N->getOperand(AddrOpIdx + 1); 2199 assert(isa<ConstantSDNode>(Inc.getNode()) && 2200 "only constant post-increment update allowed for VLD3/4"); 2201 (void)Inc; 2202 Ops.push_back(Reg0); 2203 } 2204 Ops.push_back(SDValue(VLdA, 0)); 2205 Ops.push_back(Pred); 2206 Ops.push_back(Reg0); 2207 Ops.push_back(Chain); 2208 VLd = CurDAG->getMachineNode(QOpcodes1[OpcodeIndex], dl, ResTys, Ops); 2209 } 2210 2211 // Transfer memoperands. 2212 MachineMemOperand *MemOp = cast<MemIntrinsicSDNode>(N)->getMemOperand(); 2213 CurDAG->setNodeMemRefs(cast<MachineSDNode>(VLd), {MemOp}); 2214 2215 if (NumVecs == 1) { 2216 ReplaceNode(N, VLd); 2217 return; 2218 } 2219 2220 // Extract out the subregisters. 2221 SDValue SuperReg = SDValue(VLd, 0); 2222 static_assert(ARM::dsub_7 == ARM::dsub_0 + 7 && 2223 ARM::qsub_3 == ARM::qsub_0 + 3, 2224 "Unexpected subreg numbering"); 2225 unsigned Sub0 = (is64BitVector ? ARM::dsub_0 : ARM::qsub_0); 2226 for (unsigned Vec = 0; Vec < NumVecs; ++Vec) 2227 ReplaceUses(SDValue(N, Vec), 2228 CurDAG->getTargetExtractSubreg(Sub0 + Vec, dl, VT, SuperReg)); 2229 ReplaceUses(SDValue(N, NumVecs), SDValue(VLd, 1)); 2230 if (isUpdating) 2231 ReplaceUses(SDValue(N, NumVecs + 1), SDValue(VLd, 2)); 2232 CurDAG->RemoveDeadNode(N); 2233 } 2234 2235 void ARMDAGToDAGISel::SelectVST(SDNode *N, bool isUpdating, unsigned NumVecs, 2236 const uint16_t *DOpcodes, 2237 const uint16_t *QOpcodes0, 2238 const uint16_t *QOpcodes1) { 2239 assert(Subtarget->hasNEON()); 2240 assert(NumVecs >= 1 && NumVecs <= 4 && "VST NumVecs out-of-range"); 2241 SDLoc dl(N); 2242 2243 SDValue MemAddr, Align; 2244 bool IsIntrinsic = !isUpdating; // By coincidence, all supported updating 2245 // nodes are not intrinsics. 2246 unsigned AddrOpIdx = IsIntrinsic ? 2 : 1; 2247 unsigned Vec0Idx = 3; // AddrOpIdx + (isUpdating ? 2 : 1) 2248 if (!SelectAddrMode6(N, N->getOperand(AddrOpIdx), MemAddr, Align)) 2249 return; 2250 2251 MachineMemOperand *MemOp = cast<MemIntrinsicSDNode>(N)->getMemOperand(); 2252 2253 SDValue Chain = N->getOperand(0); 2254 EVT VT = N->getOperand(Vec0Idx).getValueType(); 2255 bool is64BitVector = VT.is64BitVector(); 2256 Align = GetVLDSTAlign(Align, dl, NumVecs, is64BitVector); 2257 2258 unsigned OpcodeIndex; 2259 switch (VT.getSimpleVT().SimpleTy) { 2260 default: llvm_unreachable("unhandled vst type"); 2261 // Double-register operations: 2262 case MVT::v8i8: OpcodeIndex = 0; break; 2263 case MVT::v4f16: 2264 case MVT::v4bf16: 2265 case MVT::v4i16: OpcodeIndex = 1; break; 2266 case MVT::v2f32: 2267 case MVT::v2i32: OpcodeIndex = 2; break; 2268 case MVT::v1i64: OpcodeIndex = 3; break; 2269 // Quad-register operations: 2270 case MVT::v16i8: OpcodeIndex = 0; break; 2271 case MVT::v8f16: 2272 case MVT::v8bf16: 2273 case MVT::v8i16: OpcodeIndex = 1; break; 2274 case MVT::v4f32: 2275 case MVT::v4i32: OpcodeIndex = 2; break; 2276 case MVT::v2f64: 2277 case MVT::v2i64: OpcodeIndex = 3; break; 2278 } 2279 2280 std::vector<EVT> ResTys; 2281 if (isUpdating) 2282 ResTys.push_back(MVT::i32); 2283 ResTys.push_back(MVT::Other); 2284 2285 SDValue Pred = getAL(CurDAG, dl); 2286 SDValue Reg0 = CurDAG->getRegister(0, MVT::i32); 2287 SmallVector<SDValue, 7> Ops; 2288 2289 // Double registers and VST1/VST2 quad registers are directly supported. 2290 if (is64BitVector || NumVecs <= 2) { 2291 SDValue SrcReg; 2292 if (NumVecs == 1) { 2293 SrcReg = N->getOperand(Vec0Idx); 2294 } else if (is64BitVector) { 2295 // Form a REG_SEQUENCE to force register allocation. 2296 SDValue V0 = N->getOperand(Vec0Idx + 0); 2297 SDValue V1 = N->getOperand(Vec0Idx + 1); 2298 if (NumVecs == 2) 2299 SrcReg = SDValue(createDRegPairNode(MVT::v2i64, V0, V1), 0); 2300 else { 2301 SDValue V2 = N->getOperand(Vec0Idx + 2); 2302 // If it's a vst3, form a quad D-register and leave the last part as 2303 // an undef. 2304 SDValue V3 = (NumVecs == 3) 2305 ? SDValue(CurDAG->getMachineNode(TargetOpcode::IMPLICIT_DEF,dl,VT), 0) 2306 : N->getOperand(Vec0Idx + 3); 2307 SrcReg = SDValue(createQuadDRegsNode(MVT::v4i64, V0, V1, V2, V3), 0); 2308 } 2309 } else { 2310 // Form a QQ register. 2311 SDValue Q0 = N->getOperand(Vec0Idx); 2312 SDValue Q1 = N->getOperand(Vec0Idx + 1); 2313 SrcReg = SDValue(createQRegPairNode(MVT::v4i64, Q0, Q1), 0); 2314 } 2315 2316 unsigned Opc = (is64BitVector ? DOpcodes[OpcodeIndex] : 2317 QOpcodes0[OpcodeIndex]); 2318 Ops.push_back(MemAddr); 2319 Ops.push_back(Align); 2320 if (isUpdating) { 2321 SDValue Inc = N->getOperand(AddrOpIdx + 1); 2322 bool IsImmUpdate = isPerfectIncrement(Inc, VT, NumVecs); 2323 if (!IsImmUpdate) { 2324 // We use a VST1 for v1i64 even if the pseudo says VST2/3/4, so 2325 // check for the opcode rather than the number of vector elements. 2326 if (isVSTfixed(Opc)) 2327 Opc = getVLDSTRegisterUpdateOpcode(Opc); 2328 Ops.push_back(Inc); 2329 } 2330 // VST1/VST2 fixed increment does not need Reg0 so only include it in 2331 // the operands if not such an opcode. 2332 else if (!isVSTfixed(Opc)) 2333 Ops.push_back(Reg0); 2334 } 2335 Ops.push_back(SrcReg); 2336 Ops.push_back(Pred); 2337 Ops.push_back(Reg0); 2338 Ops.push_back(Chain); 2339 SDNode *VSt = CurDAG->getMachineNode(Opc, dl, ResTys, Ops); 2340 2341 // Transfer memoperands. 2342 CurDAG->setNodeMemRefs(cast<MachineSDNode>(VSt), {MemOp}); 2343 2344 ReplaceNode(N, VSt); 2345 return; 2346 } 2347 2348 // Otherwise, quad registers are stored with two separate instructions, 2349 // where one stores the even registers and the other stores the odd registers. 2350 2351 // Form the QQQQ REG_SEQUENCE. 2352 SDValue V0 = N->getOperand(Vec0Idx + 0); 2353 SDValue V1 = N->getOperand(Vec0Idx + 1); 2354 SDValue V2 = N->getOperand(Vec0Idx + 2); 2355 SDValue V3 = (NumVecs == 3) 2356 ? SDValue(CurDAG->getMachineNode(TargetOpcode::IMPLICIT_DEF, dl, VT), 0) 2357 : N->getOperand(Vec0Idx + 3); 2358 SDValue RegSeq = SDValue(createQuadQRegsNode(MVT::v8i64, V0, V1, V2, V3), 0); 2359 2360 // Store the even D registers. This is always an updating store, so that it 2361 // provides the address to the second store for the odd subregs. 2362 const SDValue OpsA[] = { MemAddr, Align, Reg0, RegSeq, Pred, Reg0, Chain }; 2363 SDNode *VStA = CurDAG->getMachineNode(QOpcodes0[OpcodeIndex], dl, 2364 MemAddr.getValueType(), 2365 MVT::Other, OpsA); 2366 CurDAG->setNodeMemRefs(cast<MachineSDNode>(VStA), {MemOp}); 2367 Chain = SDValue(VStA, 1); 2368 2369 // Store the odd D registers. 2370 Ops.push_back(SDValue(VStA, 0)); 2371 Ops.push_back(Align); 2372 if (isUpdating) { 2373 SDValue Inc = N->getOperand(AddrOpIdx + 1); 2374 assert(isa<ConstantSDNode>(Inc.getNode()) && 2375 "only constant post-increment update allowed for VST3/4"); 2376 (void)Inc; 2377 Ops.push_back(Reg0); 2378 } 2379 Ops.push_back(RegSeq); 2380 Ops.push_back(Pred); 2381 Ops.push_back(Reg0); 2382 Ops.push_back(Chain); 2383 SDNode *VStB = CurDAG->getMachineNode(QOpcodes1[OpcodeIndex], dl, ResTys, 2384 Ops); 2385 CurDAG->setNodeMemRefs(cast<MachineSDNode>(VStB), {MemOp}); 2386 ReplaceNode(N, VStB); 2387 } 2388 2389 void ARMDAGToDAGISel::SelectVLDSTLane(SDNode *N, bool IsLoad, bool isUpdating, 2390 unsigned NumVecs, 2391 const uint16_t *DOpcodes, 2392 const uint16_t *QOpcodes) { 2393 assert(Subtarget->hasNEON()); 2394 assert(NumVecs >=2 && NumVecs <= 4 && "VLDSTLane NumVecs out-of-range"); 2395 SDLoc dl(N); 2396 2397 SDValue MemAddr, Align; 2398 bool IsIntrinsic = !isUpdating; // By coincidence, all supported updating 2399 // nodes are not intrinsics. 2400 unsigned AddrOpIdx = IsIntrinsic ? 2 : 1; 2401 unsigned Vec0Idx = 3; // AddrOpIdx + (isUpdating ? 2 : 1) 2402 if (!SelectAddrMode6(N, N->getOperand(AddrOpIdx), MemAddr, Align)) 2403 return; 2404 2405 MachineMemOperand *MemOp = cast<MemIntrinsicSDNode>(N)->getMemOperand(); 2406 2407 SDValue Chain = N->getOperand(0); 2408 unsigned Lane = 2409 cast<ConstantSDNode>(N->getOperand(Vec0Idx + NumVecs))->getZExtValue(); 2410 EVT VT = N->getOperand(Vec0Idx).getValueType(); 2411 bool is64BitVector = VT.is64BitVector(); 2412 2413 unsigned Alignment = 0; 2414 if (NumVecs != 3) { 2415 Alignment = cast<ConstantSDNode>(Align)->getZExtValue(); 2416 unsigned NumBytes = NumVecs * VT.getScalarSizeInBits() / 8; 2417 if (Alignment > NumBytes) 2418 Alignment = NumBytes; 2419 if (Alignment < 8 && Alignment < NumBytes) 2420 Alignment = 0; 2421 // Alignment must be a power of two; make sure of that. 2422 Alignment = (Alignment & -Alignment); 2423 if (Alignment == 1) 2424 Alignment = 0; 2425 } 2426 Align = CurDAG->getTargetConstant(Alignment, dl, MVT::i32); 2427 2428 unsigned OpcodeIndex; 2429 switch (VT.getSimpleVT().SimpleTy) { 2430 default: llvm_unreachable("unhandled vld/vst lane type"); 2431 // Double-register operations: 2432 case MVT::v8i8: OpcodeIndex = 0; break; 2433 case MVT::v4f16: 2434 case MVT::v4bf16: 2435 case MVT::v4i16: OpcodeIndex = 1; break; 2436 case MVT::v2f32: 2437 case MVT::v2i32: OpcodeIndex = 2; break; 2438 // Quad-register operations: 2439 case MVT::v8f16: 2440 case MVT::v8bf16: 2441 case MVT::v8i16: OpcodeIndex = 0; break; 2442 case MVT::v4f32: 2443 case MVT::v4i32: OpcodeIndex = 1; break; 2444 } 2445 2446 std::vector<EVT> ResTys; 2447 if (IsLoad) { 2448 unsigned ResTyElts = (NumVecs == 3) ? 4 : NumVecs; 2449 if (!is64BitVector) 2450 ResTyElts *= 2; 2451 ResTys.push_back(EVT::getVectorVT(*CurDAG->getContext(), 2452 MVT::i64, ResTyElts)); 2453 } 2454 if (isUpdating) 2455 ResTys.push_back(MVT::i32); 2456 ResTys.push_back(MVT::Other); 2457 2458 SDValue Pred = getAL(CurDAG, dl); 2459 SDValue Reg0 = CurDAG->getRegister(0, MVT::i32); 2460 2461 SmallVector<SDValue, 8> Ops; 2462 Ops.push_back(MemAddr); 2463 Ops.push_back(Align); 2464 if (isUpdating) { 2465 SDValue Inc = N->getOperand(AddrOpIdx + 1); 2466 bool IsImmUpdate = 2467 isPerfectIncrement(Inc, VT.getVectorElementType(), NumVecs); 2468 Ops.push_back(IsImmUpdate ? Reg0 : Inc); 2469 } 2470 2471 SDValue SuperReg; 2472 SDValue V0 = N->getOperand(Vec0Idx + 0); 2473 SDValue V1 = N->getOperand(Vec0Idx + 1); 2474 if (NumVecs == 2) { 2475 if (is64BitVector) 2476 SuperReg = SDValue(createDRegPairNode(MVT::v2i64, V0, V1), 0); 2477 else 2478 SuperReg = SDValue(createQRegPairNode(MVT::v4i64, V0, V1), 0); 2479 } else { 2480 SDValue V2 = N->getOperand(Vec0Idx + 2); 2481 SDValue V3 = (NumVecs == 3) 2482 ? SDValue(CurDAG->getMachineNode(TargetOpcode::IMPLICIT_DEF, dl, VT), 0) 2483 : N->getOperand(Vec0Idx + 3); 2484 if (is64BitVector) 2485 SuperReg = SDValue(createQuadDRegsNode(MVT::v4i64, V0, V1, V2, V3), 0); 2486 else 2487 SuperReg = SDValue(createQuadQRegsNode(MVT::v8i64, V0, V1, V2, V3), 0); 2488 } 2489 Ops.push_back(SuperReg); 2490 Ops.push_back(getI32Imm(Lane, dl)); 2491 Ops.push_back(Pred); 2492 Ops.push_back(Reg0); 2493 Ops.push_back(Chain); 2494 2495 unsigned Opc = (is64BitVector ? DOpcodes[OpcodeIndex] : 2496 QOpcodes[OpcodeIndex]); 2497 SDNode *VLdLn = CurDAG->getMachineNode(Opc, dl, ResTys, Ops); 2498 CurDAG->setNodeMemRefs(cast<MachineSDNode>(VLdLn), {MemOp}); 2499 if (!IsLoad) { 2500 ReplaceNode(N, VLdLn); 2501 return; 2502 } 2503 2504 // Extract the subregisters. 2505 SuperReg = SDValue(VLdLn, 0); 2506 static_assert(ARM::dsub_7 == ARM::dsub_0 + 7 && 2507 ARM::qsub_3 == ARM::qsub_0 + 3, 2508 "Unexpected subreg numbering"); 2509 unsigned Sub0 = is64BitVector ? ARM::dsub_0 : ARM::qsub_0; 2510 for (unsigned Vec = 0; Vec < NumVecs; ++Vec) 2511 ReplaceUses(SDValue(N, Vec), 2512 CurDAG->getTargetExtractSubreg(Sub0 + Vec, dl, VT, SuperReg)); 2513 ReplaceUses(SDValue(N, NumVecs), SDValue(VLdLn, 1)); 2514 if (isUpdating) 2515 ReplaceUses(SDValue(N, NumVecs + 1), SDValue(VLdLn, 2)); 2516 CurDAG->RemoveDeadNode(N); 2517 } 2518 2519 template <typename SDValueVector> 2520 void ARMDAGToDAGISel::AddMVEPredicateToOps(SDValueVector &Ops, SDLoc Loc, 2521 SDValue PredicateMask) { 2522 Ops.push_back(CurDAG->getTargetConstant(ARMVCC::Then, Loc, MVT::i32)); 2523 Ops.push_back(PredicateMask); 2524 } 2525 2526 template <typename SDValueVector> 2527 void ARMDAGToDAGISel::AddMVEPredicateToOps(SDValueVector &Ops, SDLoc Loc, 2528 SDValue PredicateMask, 2529 SDValue Inactive) { 2530 Ops.push_back(CurDAG->getTargetConstant(ARMVCC::Then, Loc, MVT::i32)); 2531 Ops.push_back(PredicateMask); 2532 Ops.push_back(Inactive); 2533 } 2534 2535 template <typename SDValueVector> 2536 void ARMDAGToDAGISel::AddEmptyMVEPredicateToOps(SDValueVector &Ops, SDLoc Loc) { 2537 Ops.push_back(CurDAG->getTargetConstant(ARMVCC::None, Loc, MVT::i32)); 2538 Ops.push_back(CurDAG->getRegister(0, MVT::i32)); 2539 } 2540 2541 template <typename SDValueVector> 2542 void ARMDAGToDAGISel::AddEmptyMVEPredicateToOps(SDValueVector &Ops, SDLoc Loc, 2543 EVT InactiveTy) { 2544 Ops.push_back(CurDAG->getTargetConstant(ARMVCC::None, Loc, MVT::i32)); 2545 Ops.push_back(CurDAG->getRegister(0, MVT::i32)); 2546 Ops.push_back(SDValue( 2547 CurDAG->getMachineNode(TargetOpcode::IMPLICIT_DEF, Loc, InactiveTy), 0)); 2548 } 2549 2550 void ARMDAGToDAGISel::SelectMVE_WB(SDNode *N, const uint16_t *Opcodes, 2551 bool Predicated) { 2552 SDLoc Loc(N); 2553 SmallVector<SDValue, 8> Ops; 2554 2555 uint16_t Opcode; 2556 switch (N->getValueType(1).getVectorElementType().getSizeInBits()) { 2557 case 32: 2558 Opcode = Opcodes[0]; 2559 break; 2560 case 64: 2561 Opcode = Opcodes[1]; 2562 break; 2563 default: 2564 llvm_unreachable("bad vector element size in SelectMVE_WB"); 2565 } 2566 2567 Ops.push_back(N->getOperand(2)); // vector of base addresses 2568 2569 int32_t ImmValue = cast<ConstantSDNode>(N->getOperand(3))->getZExtValue(); 2570 Ops.push_back(getI32Imm(ImmValue, Loc)); // immediate offset 2571 2572 if (Predicated) 2573 AddMVEPredicateToOps(Ops, Loc, N->getOperand(4)); 2574 else 2575 AddEmptyMVEPredicateToOps(Ops, Loc); 2576 2577 Ops.push_back(N->getOperand(0)); // chain 2578 2579 SmallVector<EVT, 8> VTs; 2580 VTs.push_back(N->getValueType(1)); 2581 VTs.push_back(N->getValueType(0)); 2582 VTs.push_back(N->getValueType(2)); 2583 2584 SDNode *New = CurDAG->getMachineNode(Opcode, SDLoc(N), VTs, Ops); 2585 ReplaceUses(SDValue(N, 0), SDValue(New, 1)); 2586 ReplaceUses(SDValue(N, 1), SDValue(New, 0)); 2587 ReplaceUses(SDValue(N, 2), SDValue(New, 2)); 2588 transferMemOperands(N, New); 2589 CurDAG->RemoveDeadNode(N); 2590 } 2591 2592 void ARMDAGToDAGISel::SelectMVE_LongShift(SDNode *N, uint16_t Opcode, 2593 bool Immediate, 2594 bool HasSaturationOperand) { 2595 SDLoc Loc(N); 2596 SmallVector<SDValue, 8> Ops; 2597 2598 // Two 32-bit halves of the value to be shifted 2599 Ops.push_back(N->getOperand(1)); 2600 Ops.push_back(N->getOperand(2)); 2601 2602 // The shift count 2603 if (Immediate) { 2604 int32_t ImmValue = cast<ConstantSDNode>(N->getOperand(3))->getZExtValue(); 2605 Ops.push_back(getI32Imm(ImmValue, Loc)); // immediate shift count 2606 } else { 2607 Ops.push_back(N->getOperand(3)); 2608 } 2609 2610 // The immediate saturation operand, if any 2611 if (HasSaturationOperand) { 2612 int32_t SatOp = cast<ConstantSDNode>(N->getOperand(4))->getZExtValue(); 2613 int SatBit = (SatOp == 64 ? 0 : 1); 2614 Ops.push_back(getI32Imm(SatBit, Loc)); 2615 } 2616 2617 // MVE scalar shifts are IT-predicable, so include the standard 2618 // predicate arguments. 2619 Ops.push_back(getAL(CurDAG, Loc)); 2620 Ops.push_back(CurDAG->getRegister(0, MVT::i32)); 2621 2622 CurDAG->SelectNodeTo(N, Opcode, N->getVTList(), makeArrayRef(Ops)); 2623 } 2624 2625 void ARMDAGToDAGISel::SelectMVE_VADCSBC(SDNode *N, uint16_t OpcodeWithCarry, 2626 uint16_t OpcodeWithNoCarry, 2627 bool Add, bool Predicated) { 2628 SDLoc Loc(N); 2629 SmallVector<SDValue, 8> Ops; 2630 uint16_t Opcode; 2631 2632 unsigned FirstInputOp = Predicated ? 2 : 1; 2633 2634 // Two input vectors and the input carry flag 2635 Ops.push_back(N->getOperand(FirstInputOp)); 2636 Ops.push_back(N->getOperand(FirstInputOp + 1)); 2637 SDValue CarryIn = N->getOperand(FirstInputOp + 2); 2638 ConstantSDNode *CarryInConstant = dyn_cast<ConstantSDNode>(CarryIn); 2639 uint32_t CarryMask = 1 << 29; 2640 uint32_t CarryExpected = Add ? 0 : CarryMask; 2641 if (CarryInConstant && 2642 (CarryInConstant->getZExtValue() & CarryMask) == CarryExpected) { 2643 Opcode = OpcodeWithNoCarry; 2644 } else { 2645 Ops.push_back(CarryIn); 2646 Opcode = OpcodeWithCarry; 2647 } 2648 2649 if (Predicated) 2650 AddMVEPredicateToOps(Ops, Loc, 2651 N->getOperand(FirstInputOp + 3), // predicate 2652 N->getOperand(FirstInputOp - 1)); // inactive 2653 else 2654 AddEmptyMVEPredicateToOps(Ops, Loc, N->getValueType(0)); 2655 2656 CurDAG->SelectNodeTo(N, Opcode, N->getVTList(), makeArrayRef(Ops)); 2657 } 2658 2659 void ARMDAGToDAGISel::SelectMVE_VSHLC(SDNode *N, bool Predicated) { 2660 SDLoc Loc(N); 2661 SmallVector<SDValue, 8> Ops; 2662 2663 // One vector input, followed by a 32-bit word of bits to shift in 2664 // and then an immediate shift count 2665 Ops.push_back(N->getOperand(1)); 2666 Ops.push_back(N->getOperand(2)); 2667 int32_t ImmValue = cast<ConstantSDNode>(N->getOperand(3))->getZExtValue(); 2668 Ops.push_back(getI32Imm(ImmValue, Loc)); // immediate shift count 2669 2670 if (Predicated) 2671 AddMVEPredicateToOps(Ops, Loc, N->getOperand(4)); 2672 else 2673 AddEmptyMVEPredicateToOps(Ops, Loc); 2674 2675 CurDAG->SelectNodeTo(N, ARM::MVE_VSHLC, N->getVTList(), makeArrayRef(Ops)); 2676 } 2677 2678 static bool SDValueToConstBool(SDValue SDVal) { 2679 assert(isa<ConstantSDNode>(SDVal) && "expected a compile-time constant"); 2680 ConstantSDNode *SDValConstant = dyn_cast<ConstantSDNode>(SDVal); 2681 uint64_t Value = SDValConstant->getZExtValue(); 2682 assert((Value == 0 || Value == 1) && "expected value 0 or 1"); 2683 return Value; 2684 } 2685 2686 void ARMDAGToDAGISel::SelectBaseMVE_VMLLDAV(SDNode *N, bool Predicated, 2687 const uint16_t *OpcodesS, 2688 const uint16_t *OpcodesU, 2689 size_t Stride, size_t TySize) { 2690 assert(TySize < Stride && "Invalid TySize"); 2691 bool IsUnsigned = SDValueToConstBool(N->getOperand(1)); 2692 bool IsSub = SDValueToConstBool(N->getOperand(2)); 2693 bool IsExchange = SDValueToConstBool(N->getOperand(3)); 2694 if (IsUnsigned) { 2695 assert(!IsSub && 2696 "Unsigned versions of vmlsldav[a]/vrmlsldavh[a] do not exist"); 2697 assert(!IsExchange && 2698 "Unsigned versions of vmlaldav[a]x/vrmlaldavh[a]x do not exist"); 2699 } 2700 2701 auto OpIsZero = [N](size_t OpNo) { 2702 if (ConstantSDNode *OpConst = dyn_cast<ConstantSDNode>(N->getOperand(OpNo))) 2703 if (OpConst->getZExtValue() == 0) 2704 return true; 2705 return false; 2706 }; 2707 2708 // If the input accumulator value is not zero, select an instruction with 2709 // accumulator, otherwise select an instruction without accumulator 2710 bool IsAccum = !(OpIsZero(4) && OpIsZero(5)); 2711 2712 const uint16_t *Opcodes = IsUnsigned ? OpcodesU : OpcodesS; 2713 if (IsSub) 2714 Opcodes += 4 * Stride; 2715 if (IsExchange) 2716 Opcodes += 2 * Stride; 2717 if (IsAccum) 2718 Opcodes += Stride; 2719 uint16_t Opcode = Opcodes[TySize]; 2720 2721 SDLoc Loc(N); 2722 SmallVector<SDValue, 8> Ops; 2723 // Push the accumulator operands, if they are used 2724 if (IsAccum) { 2725 Ops.push_back(N->getOperand(4)); 2726 Ops.push_back(N->getOperand(5)); 2727 } 2728 // Push the two vector operands 2729 Ops.push_back(N->getOperand(6)); 2730 Ops.push_back(N->getOperand(7)); 2731 2732 if (Predicated) 2733 AddMVEPredicateToOps(Ops, Loc, N->getOperand(8)); 2734 else 2735 AddEmptyMVEPredicateToOps(Ops, Loc); 2736 2737 CurDAG->SelectNodeTo(N, Opcode, N->getVTList(), makeArrayRef(Ops)); 2738 } 2739 2740 void ARMDAGToDAGISel::SelectMVE_VMLLDAV(SDNode *N, bool Predicated, 2741 const uint16_t *OpcodesS, 2742 const uint16_t *OpcodesU) { 2743 EVT VecTy = N->getOperand(6).getValueType(); 2744 size_t SizeIndex; 2745 switch (VecTy.getVectorElementType().getSizeInBits()) { 2746 case 16: 2747 SizeIndex = 0; 2748 break; 2749 case 32: 2750 SizeIndex = 1; 2751 break; 2752 default: 2753 llvm_unreachable("bad vector element size"); 2754 } 2755 2756 SelectBaseMVE_VMLLDAV(N, Predicated, OpcodesS, OpcodesU, 2, SizeIndex); 2757 } 2758 2759 void ARMDAGToDAGISel::SelectMVE_VRMLLDAVH(SDNode *N, bool Predicated, 2760 const uint16_t *OpcodesS, 2761 const uint16_t *OpcodesU) { 2762 assert( 2763 N->getOperand(6).getValueType().getVectorElementType().getSizeInBits() == 2764 32 && 2765 "bad vector element size"); 2766 SelectBaseMVE_VMLLDAV(N, Predicated, OpcodesS, OpcodesU, 1, 0); 2767 } 2768 2769 void ARMDAGToDAGISel::SelectMVE_VLD(SDNode *N, unsigned NumVecs, 2770 const uint16_t *const *Opcodes, 2771 bool HasWriteback) { 2772 EVT VT = N->getValueType(0); 2773 SDLoc Loc(N); 2774 2775 const uint16_t *OurOpcodes; 2776 switch (VT.getVectorElementType().getSizeInBits()) { 2777 case 8: 2778 OurOpcodes = Opcodes[0]; 2779 break; 2780 case 16: 2781 OurOpcodes = Opcodes[1]; 2782 break; 2783 case 32: 2784 OurOpcodes = Opcodes[2]; 2785 break; 2786 default: 2787 llvm_unreachable("bad vector element size in SelectMVE_VLD"); 2788 } 2789 2790 EVT DataTy = EVT::getVectorVT(*CurDAG->getContext(), MVT::i64, NumVecs * 2); 2791 SmallVector<EVT, 4> ResultTys = {DataTy, MVT::Other}; 2792 unsigned PtrOperand = HasWriteback ? 1 : 2; 2793 2794 auto Data = SDValue( 2795 CurDAG->getMachineNode(TargetOpcode::IMPLICIT_DEF, Loc, DataTy), 0); 2796 SDValue Chain = N->getOperand(0); 2797 // Add a MVE_VLDn instruction for each Vec, except the last 2798 for (unsigned Stage = 0; Stage < NumVecs - 1; ++Stage) { 2799 SDValue Ops[] = {Data, N->getOperand(PtrOperand), Chain}; 2800 auto LoadInst = 2801 CurDAG->getMachineNode(OurOpcodes[Stage], Loc, ResultTys, Ops); 2802 Data = SDValue(LoadInst, 0); 2803 Chain = SDValue(LoadInst, 1); 2804 transferMemOperands(N, LoadInst); 2805 } 2806 // The last may need a writeback on it 2807 if (HasWriteback) 2808 ResultTys = {DataTy, MVT::i32, MVT::Other}; 2809 SDValue Ops[] = {Data, N->getOperand(PtrOperand), Chain}; 2810 auto LoadInst = 2811 CurDAG->getMachineNode(OurOpcodes[NumVecs - 1], Loc, ResultTys, Ops); 2812 transferMemOperands(N, LoadInst); 2813 2814 unsigned i; 2815 for (i = 0; i < NumVecs; i++) 2816 ReplaceUses(SDValue(N, i), 2817 CurDAG->getTargetExtractSubreg(ARM::qsub_0 + i, Loc, VT, 2818 SDValue(LoadInst, 0))); 2819 if (HasWriteback) 2820 ReplaceUses(SDValue(N, i++), SDValue(LoadInst, 1)); 2821 ReplaceUses(SDValue(N, i), SDValue(LoadInst, HasWriteback ? 2 : 1)); 2822 CurDAG->RemoveDeadNode(N); 2823 } 2824 2825 void ARMDAGToDAGISel::SelectMVE_VxDUP(SDNode *N, const uint16_t *Opcodes, 2826 bool Wrapping, bool Predicated) { 2827 EVT VT = N->getValueType(0); 2828 SDLoc Loc(N); 2829 2830 uint16_t Opcode; 2831 switch (VT.getScalarSizeInBits()) { 2832 case 8: 2833 Opcode = Opcodes[0]; 2834 break; 2835 case 16: 2836 Opcode = Opcodes[1]; 2837 break; 2838 case 32: 2839 Opcode = Opcodes[2]; 2840 break; 2841 default: 2842 llvm_unreachable("bad vector element size in SelectMVE_VxDUP"); 2843 } 2844 2845 SmallVector<SDValue, 8> Ops; 2846 unsigned OpIdx = 1; 2847 2848 SDValue Inactive; 2849 if (Predicated) 2850 Inactive = N->getOperand(OpIdx++); 2851 2852 Ops.push_back(N->getOperand(OpIdx++)); // base 2853 if (Wrapping) 2854 Ops.push_back(N->getOperand(OpIdx++)); // limit 2855 2856 SDValue ImmOp = N->getOperand(OpIdx++); // step 2857 int ImmValue = cast<ConstantSDNode>(ImmOp)->getZExtValue(); 2858 Ops.push_back(getI32Imm(ImmValue, Loc)); 2859 2860 if (Predicated) 2861 AddMVEPredicateToOps(Ops, Loc, N->getOperand(OpIdx), Inactive); 2862 else 2863 AddEmptyMVEPredicateToOps(Ops, Loc, N->getValueType(0)); 2864 2865 CurDAG->SelectNodeTo(N, Opcode, N->getVTList(), makeArrayRef(Ops)); 2866 } 2867 2868 void ARMDAGToDAGISel::SelectCDE_CXxD(SDNode *N, uint16_t Opcode, 2869 size_t NumExtraOps, bool HasAccum) { 2870 bool IsBigEndian = CurDAG->getDataLayout().isBigEndian(); 2871 SDLoc Loc(N); 2872 SmallVector<SDValue, 8> Ops; 2873 2874 unsigned OpIdx = 1; 2875 2876 // Convert and append the immediate operand designating the coprocessor. 2877 SDValue ImmCorpoc = N->getOperand(OpIdx++); 2878 uint32_t ImmCoprocVal = cast<ConstantSDNode>(ImmCorpoc)->getZExtValue(); 2879 Ops.push_back(getI32Imm(ImmCoprocVal, Loc)); 2880 2881 // For accumulating variants copy the low and high order parts of the 2882 // accumulator into a register pair and add it to the operand vector. 2883 if (HasAccum) { 2884 SDValue AccLo = N->getOperand(OpIdx++); 2885 SDValue AccHi = N->getOperand(OpIdx++); 2886 if (IsBigEndian) 2887 std::swap(AccLo, AccHi); 2888 Ops.push_back(SDValue(createGPRPairNode(MVT::Untyped, AccLo, AccHi), 0)); 2889 } 2890 2891 // Copy extra operands as-is. 2892 for (size_t I = 0; I < NumExtraOps; I++) 2893 Ops.push_back(N->getOperand(OpIdx++)); 2894 2895 // Convert and append the immediate operand 2896 SDValue Imm = N->getOperand(OpIdx); 2897 uint32_t ImmVal = cast<ConstantSDNode>(Imm)->getZExtValue(); 2898 Ops.push_back(getI32Imm(ImmVal, Loc)); 2899 2900 // Accumulating variants are IT-predicable, add predicate operands. 2901 if (HasAccum) { 2902 SDValue Pred = getAL(CurDAG, Loc); 2903 SDValue PredReg = CurDAG->getRegister(0, MVT::i32); 2904 Ops.push_back(Pred); 2905 Ops.push_back(PredReg); 2906 } 2907 2908 // Create the CDE intruction 2909 SDNode *InstrNode = CurDAG->getMachineNode(Opcode, Loc, MVT::Untyped, Ops); 2910 SDValue ResultPair = SDValue(InstrNode, 0); 2911 2912 // The original intrinsic had two outputs, and the output of the dual-register 2913 // CDE instruction is a register pair. We need to extract the two subregisters 2914 // and replace all uses of the original outputs with the extracted 2915 // subregisters. 2916 uint16_t SubRegs[2] = {ARM::gsub_0, ARM::gsub_1}; 2917 if (IsBigEndian) 2918 std::swap(SubRegs[0], SubRegs[1]); 2919 2920 for (size_t ResIdx = 0; ResIdx < 2; ResIdx++) { 2921 if (SDValue(N, ResIdx).use_empty()) 2922 continue; 2923 SDValue SubReg = CurDAG->getTargetExtractSubreg(SubRegs[ResIdx], Loc, 2924 MVT::i32, ResultPair); 2925 ReplaceUses(SDValue(N, ResIdx), SubReg); 2926 } 2927 2928 CurDAG->RemoveDeadNode(N); 2929 } 2930 2931 void ARMDAGToDAGISel::SelectVLDDup(SDNode *N, bool IsIntrinsic, 2932 bool isUpdating, unsigned NumVecs, 2933 const uint16_t *DOpcodes, 2934 const uint16_t *QOpcodes0, 2935 const uint16_t *QOpcodes1) { 2936 assert(Subtarget->hasNEON()); 2937 assert(NumVecs >= 1 && NumVecs <= 4 && "VLDDup NumVecs out-of-range"); 2938 SDLoc dl(N); 2939 2940 SDValue MemAddr, Align; 2941 unsigned AddrOpIdx = IsIntrinsic ? 2 : 1; 2942 if (!SelectAddrMode6(N, N->getOperand(AddrOpIdx), MemAddr, Align)) 2943 return; 2944 2945 SDValue Chain = N->getOperand(0); 2946 EVT VT = N->getValueType(0); 2947 bool is64BitVector = VT.is64BitVector(); 2948 2949 unsigned Alignment = 0; 2950 if (NumVecs != 3) { 2951 Alignment = cast<ConstantSDNode>(Align)->getZExtValue(); 2952 unsigned NumBytes = NumVecs * VT.getScalarSizeInBits() / 8; 2953 if (Alignment > NumBytes) 2954 Alignment = NumBytes; 2955 if (Alignment < 8 && Alignment < NumBytes) 2956 Alignment = 0; 2957 // Alignment must be a power of two; make sure of that. 2958 Alignment = (Alignment & -Alignment); 2959 if (Alignment == 1) 2960 Alignment = 0; 2961 } 2962 Align = CurDAG->getTargetConstant(Alignment, dl, MVT::i32); 2963 2964 unsigned OpcodeIndex; 2965 switch (VT.getSimpleVT().SimpleTy) { 2966 default: llvm_unreachable("unhandled vld-dup type"); 2967 case MVT::v8i8: 2968 case MVT::v16i8: OpcodeIndex = 0; break; 2969 case MVT::v4i16: 2970 case MVT::v8i16: 2971 case MVT::v4f16: 2972 case MVT::v8f16: 2973 case MVT::v4bf16: 2974 case MVT::v8bf16: 2975 OpcodeIndex = 1; break; 2976 case MVT::v2f32: 2977 case MVT::v2i32: 2978 case MVT::v4f32: 2979 case MVT::v4i32: OpcodeIndex = 2; break; 2980 case MVT::v1f64: 2981 case MVT::v1i64: OpcodeIndex = 3; break; 2982 } 2983 2984 unsigned ResTyElts = (NumVecs == 3) ? 4 : NumVecs; 2985 if (!is64BitVector) 2986 ResTyElts *= 2; 2987 EVT ResTy = EVT::getVectorVT(*CurDAG->getContext(), MVT::i64, ResTyElts); 2988 2989 std::vector<EVT> ResTys; 2990 ResTys.push_back(ResTy); 2991 if (isUpdating) 2992 ResTys.push_back(MVT::i32); 2993 ResTys.push_back(MVT::Other); 2994 2995 SDValue Pred = getAL(CurDAG, dl); 2996 SDValue Reg0 = CurDAG->getRegister(0, MVT::i32); 2997 2998 SmallVector<SDValue, 6> Ops; 2999 Ops.push_back(MemAddr); 3000 Ops.push_back(Align); 3001 unsigned Opc = is64BitVector ? DOpcodes[OpcodeIndex] 3002 : (NumVecs == 1) ? QOpcodes0[OpcodeIndex] 3003 : QOpcodes1[OpcodeIndex]; 3004 if (isUpdating) { 3005 SDValue Inc = N->getOperand(2); 3006 bool IsImmUpdate = 3007 isPerfectIncrement(Inc, VT.getVectorElementType(), NumVecs); 3008 if (IsImmUpdate) { 3009 if (!isVLDfixed(Opc)) 3010 Ops.push_back(Reg0); 3011 } else { 3012 if (isVLDfixed(Opc)) 3013 Opc = getVLDSTRegisterUpdateOpcode(Opc); 3014 Ops.push_back(Inc); 3015 } 3016 } 3017 if (is64BitVector || NumVecs == 1) { 3018 // Double registers and VLD1 quad registers are directly supported. 3019 } else if (NumVecs == 2) { 3020 const SDValue OpsA[] = {MemAddr, Align, Pred, Reg0, Chain}; 3021 SDNode *VLdA = CurDAG->getMachineNode(QOpcodes0[OpcodeIndex], dl, ResTy, 3022 MVT::Other, OpsA); 3023 Chain = SDValue(VLdA, 1); 3024 } else { 3025 SDValue ImplDef = SDValue( 3026 CurDAG->getMachineNode(TargetOpcode::IMPLICIT_DEF, dl, ResTy), 0); 3027 const SDValue OpsA[] = {MemAddr, Align, ImplDef, Pred, Reg0, Chain}; 3028 SDNode *VLdA = CurDAG->getMachineNode(QOpcodes0[OpcodeIndex], dl, ResTy, 3029 MVT::Other, OpsA); 3030 Ops.push_back(SDValue(VLdA, 0)); 3031 Chain = SDValue(VLdA, 1); 3032 } 3033 3034 Ops.push_back(Pred); 3035 Ops.push_back(Reg0); 3036 Ops.push_back(Chain); 3037 3038 SDNode *VLdDup = CurDAG->getMachineNode(Opc, dl, ResTys, Ops); 3039 3040 // Transfer memoperands. 3041 MachineMemOperand *MemOp = cast<MemIntrinsicSDNode>(N)->getMemOperand(); 3042 CurDAG->setNodeMemRefs(cast<MachineSDNode>(VLdDup), {MemOp}); 3043 3044 // Extract the subregisters. 3045 if (NumVecs == 1) { 3046 ReplaceUses(SDValue(N, 0), SDValue(VLdDup, 0)); 3047 } else { 3048 SDValue SuperReg = SDValue(VLdDup, 0); 3049 static_assert(ARM::dsub_7 == ARM::dsub_0 + 7, "Unexpected subreg numbering"); 3050 unsigned SubIdx = is64BitVector ? ARM::dsub_0 : ARM::qsub_0; 3051 for (unsigned Vec = 0; Vec != NumVecs; ++Vec) { 3052 ReplaceUses(SDValue(N, Vec), 3053 CurDAG->getTargetExtractSubreg(SubIdx+Vec, dl, VT, SuperReg)); 3054 } 3055 } 3056 ReplaceUses(SDValue(N, NumVecs), SDValue(VLdDup, 1)); 3057 if (isUpdating) 3058 ReplaceUses(SDValue(N, NumVecs + 1), SDValue(VLdDup, 2)); 3059 CurDAG->RemoveDeadNode(N); 3060 } 3061 3062 bool ARMDAGToDAGISel::tryInsertVectorElt(SDNode *N) { 3063 if (!Subtarget->hasMVEIntegerOps()) 3064 return false; 3065 3066 SDLoc dl(N); 3067 3068 // We are trying to use VMOV/VMOVX/VINS to more efficiently lower insert and 3069 // extracts of v8f16 and v8i16 vectors. Check that we have two adjacent 3070 // inserts of the correct type: 3071 SDValue Ins1 = SDValue(N, 0); 3072 SDValue Ins2 = N->getOperand(0); 3073 EVT VT = Ins1.getValueType(); 3074 if (Ins2.getOpcode() != ISD::INSERT_VECTOR_ELT || !Ins2.hasOneUse() || 3075 !isa<ConstantSDNode>(Ins1.getOperand(2)) || 3076 !isa<ConstantSDNode>(Ins2.getOperand(2)) || 3077 (VT != MVT::v8f16 && VT != MVT::v8i16) || (Ins2.getValueType() != VT)) 3078 return false; 3079 3080 unsigned Lane1 = Ins1.getConstantOperandVal(2); 3081 unsigned Lane2 = Ins2.getConstantOperandVal(2); 3082 if (Lane2 % 2 != 0 || Lane1 != Lane2 + 1) 3083 return false; 3084 3085 // If the inserted values will be able to use T/B already, leave it to the 3086 // existing tablegen patterns. For example VCVTT/VCVTB. 3087 SDValue Val1 = Ins1.getOperand(1); 3088 SDValue Val2 = Ins2.getOperand(1); 3089 if (Val1.getOpcode() == ISD::FP_ROUND || Val2.getOpcode() == ISD::FP_ROUND) 3090 return false; 3091 3092 // Check if the inserted values are both extracts. 3093 if ((Val1.getOpcode() == ISD::EXTRACT_VECTOR_ELT || 3094 Val1.getOpcode() == ARMISD::VGETLANEu) && 3095 (Val2.getOpcode() == ISD::EXTRACT_VECTOR_ELT || 3096 Val2.getOpcode() == ARMISD::VGETLANEu) && 3097 isa<ConstantSDNode>(Val1.getOperand(1)) && 3098 isa<ConstantSDNode>(Val2.getOperand(1)) && 3099 (Val1.getOperand(0).getValueType() == MVT::v8f16 || 3100 Val1.getOperand(0).getValueType() == MVT::v8i16) && 3101 (Val2.getOperand(0).getValueType() == MVT::v8f16 || 3102 Val2.getOperand(0).getValueType() == MVT::v8i16)) { 3103 unsigned ExtractLane1 = Val1.getConstantOperandVal(1); 3104 unsigned ExtractLane2 = Val2.getConstantOperandVal(1); 3105 3106 // If the two extracted lanes are from the same place and adjacent, this 3107 // simplifies into a f32 lane move. 3108 if (Val1.getOperand(0) == Val2.getOperand(0) && ExtractLane2 % 2 == 0 && 3109 ExtractLane1 == ExtractLane2 + 1) { 3110 SDValue NewExt = CurDAG->getTargetExtractSubreg( 3111 ARM::ssub_0 + ExtractLane2 / 2, dl, MVT::f32, Val1.getOperand(0)); 3112 SDValue NewIns = CurDAG->getTargetInsertSubreg( 3113 ARM::ssub_0 + Lane2 / 2, dl, VT, Ins2.getOperand(0), 3114 NewExt); 3115 ReplaceUses(Ins1, NewIns); 3116 return true; 3117 } 3118 3119 // Else v8i16 pattern of an extract and an insert, with a optional vmovx for 3120 // extracting odd lanes. 3121 if (VT == MVT::v8i16) { 3122 SDValue Inp1 = CurDAG->getTargetExtractSubreg( 3123 ARM::ssub_0 + ExtractLane1 / 2, dl, MVT::f32, Val1.getOperand(0)); 3124 SDValue Inp2 = CurDAG->getTargetExtractSubreg( 3125 ARM::ssub_0 + ExtractLane2 / 2, dl, MVT::f32, Val2.getOperand(0)); 3126 if (ExtractLane1 % 2 != 0) 3127 Inp1 = SDValue(CurDAG->getMachineNode(ARM::VMOVH, dl, MVT::f32, Inp1), 0); 3128 if (ExtractLane2 % 2 != 0) 3129 Inp2 = SDValue(CurDAG->getMachineNode(ARM::VMOVH, dl, MVT::f32, Inp2), 0); 3130 SDNode *VINS = CurDAG->getMachineNode(ARM::VINSH, dl, MVT::f32, Inp2, Inp1); 3131 SDValue NewIns = 3132 CurDAG->getTargetInsertSubreg(ARM::ssub_0 + Lane2 / 2, dl, MVT::v4f32, 3133 Ins2.getOperand(0), SDValue(VINS, 0)); 3134 ReplaceUses(Ins1, NewIns); 3135 return true; 3136 } 3137 } 3138 3139 // The inserted values are not extracted - if they are f16 then insert them 3140 // directly using a VINS. 3141 if (VT == MVT::v8f16) { 3142 SDNode *VINS = CurDAG->getMachineNode(ARM::VINSH, dl, MVT::f32, Val2, Val1); 3143 SDValue NewIns = 3144 CurDAG->getTargetInsertSubreg(ARM::ssub_0 + Lane2 / 2, dl, MVT::v4f32, 3145 Ins2.getOperand(0), SDValue(VINS, 0)); 3146 ReplaceUses(Ins1, NewIns); 3147 return true; 3148 } 3149 3150 return false; 3151 } 3152 3153 bool ARMDAGToDAGISel::tryFMULFixed(SDNode *N, SDLoc dl) { 3154 // Transform a fixed-point to floating-point conversion to a VCVT 3155 if (!Subtarget->hasMVEFloatOps()) 3156 return false; 3157 auto Type = N->getValueType(0); 3158 if (!Type.isVector()) 3159 return false; 3160 3161 auto ScalarType = Type.getVectorElementType(); 3162 unsigned ScalarBits = ScalarType.getSizeInBits(); 3163 auto LHS = N->getOperand(0); 3164 auto RHS = N->getOperand(1); 3165 3166 if (ScalarBits > 32) 3167 return false; 3168 3169 if (RHS.getOpcode() == ISD::BITCAST) { 3170 if (RHS.getValueType().getVectorElementType().getSizeInBits() != ScalarBits) 3171 return false; 3172 RHS = RHS.getOperand(0); 3173 } 3174 if (RHS.getValueType().getVectorElementType().getSizeInBits() != ScalarBits) 3175 return false; 3176 if (LHS.getOpcode() != ISD::SINT_TO_FP && LHS.getOpcode() != ISD::UINT_TO_FP) 3177 return false; 3178 3179 bool IsUnsigned = LHS.getOpcode() == ISD::UINT_TO_FP; 3180 SDNodeFlags FMulFlags = N->getFlags(); 3181 // The fixed-point vcvt and vcvt+vmul are not always equivalent if inf is 3182 // allowed in 16 bit unsigned floats 3183 if (ScalarBits == 16 && !FMulFlags.hasNoInfs() && IsUnsigned) 3184 return false; 3185 3186 APFloat ImmAPF(0.0f); 3187 switch (RHS.getOpcode()) { 3188 case ARMISD::VMOVIMM: 3189 case ARMISD::VDUP: { 3190 if (!isa<ConstantSDNode>(RHS.getOperand(0))) 3191 return false; 3192 unsigned Imm = RHS.getConstantOperandVal(0); 3193 if (RHS.getOpcode() == ARMISD::VMOVIMM) 3194 Imm = ARM_AM::decodeVMOVModImm(Imm, ScalarBits); 3195 ImmAPF = 3196 APFloat(ScalarBits == 32 ? APFloat::IEEEsingle() : APFloat::IEEEhalf(), 3197 APInt(ScalarBits, Imm)); 3198 break; 3199 } 3200 case ARMISD::VMOVFPIMM: { 3201 ImmAPF = APFloat(ARM_AM::getFPImmFloat(RHS.getConstantOperandVal(0))); 3202 break; 3203 } 3204 default: 3205 return false; 3206 } 3207 3208 // Multiplying by a factor of 2^(-n) will convert from fixed point to 3209 // floating point, where n is the number of fractional bits in the fixed 3210 // point number. Taking the inverse and log2 of the factor will give n 3211 APFloat Inverse(0.0f); 3212 if (!ImmAPF.getExactInverse(&Inverse)) 3213 return false; 3214 3215 APSInt Converted(64, 0); 3216 bool IsExact; 3217 Inverse.convertToInteger(Converted, llvm::RoundingMode::NearestTiesToEven, 3218 &IsExact); 3219 if (!IsExact || !Converted.isPowerOf2()) 3220 return false; 3221 3222 unsigned FracBits = Converted.logBase2(); 3223 if (FracBits > ScalarBits) 3224 return false; 3225 3226 auto SintToFpOperand = LHS.getOperand(0); 3227 SmallVector<SDValue, 3> Ops{SintToFpOperand, 3228 CurDAG->getConstant(FracBits, dl, MVT::i32)}; 3229 AddEmptyMVEPredicateToOps(Ops, dl, Type); 3230 3231 unsigned int Opcode; 3232 switch (ScalarBits) { 3233 case 16: 3234 Opcode = IsUnsigned ? ARM::MVE_VCVTf16u16_fix : ARM::MVE_VCVTf16s16_fix; 3235 break; 3236 case 32: 3237 Opcode = IsUnsigned ? ARM::MVE_VCVTf32u32_fix : ARM::MVE_VCVTf32s32_fix; 3238 break; 3239 default: 3240 llvm_unreachable("unexpected number of scalar bits"); 3241 break; 3242 } 3243 3244 ReplaceNode(N, CurDAG->getMachineNode(Opcode, dl, Type, Ops)); 3245 return true; 3246 } 3247 3248 bool ARMDAGToDAGISel::tryV6T2BitfieldExtractOp(SDNode *N, bool isSigned) { 3249 if (!Subtarget->hasV6T2Ops()) 3250 return false; 3251 3252 unsigned Opc = isSigned 3253 ? (Subtarget->isThumb() ? ARM::t2SBFX : ARM::SBFX) 3254 : (Subtarget->isThumb() ? ARM::t2UBFX : ARM::UBFX); 3255 SDLoc dl(N); 3256 3257 // For unsigned extracts, check for a shift right and mask 3258 unsigned And_imm = 0; 3259 if (N->getOpcode() == ISD::AND) { 3260 if (isOpcWithIntImmediate(N, ISD::AND, And_imm)) { 3261 3262 // The immediate is a mask of the low bits iff imm & (imm+1) == 0 3263 if (And_imm & (And_imm + 1)) 3264 return false; 3265 3266 unsigned Srl_imm = 0; 3267 if (isOpcWithIntImmediate(N->getOperand(0).getNode(), ISD::SRL, 3268 Srl_imm)) { 3269 assert(Srl_imm > 0 && Srl_imm < 32 && "bad amount in shift node!"); 3270 3271 // Mask off the unnecessary bits of the AND immediate; normally 3272 // DAGCombine will do this, but that might not happen if 3273 // targetShrinkDemandedConstant chooses a different immediate. 3274 And_imm &= -1U >> Srl_imm; 3275 3276 // Note: The width operand is encoded as width-1. 3277 unsigned Width = countTrailingOnes(And_imm) - 1; 3278 unsigned LSB = Srl_imm; 3279 3280 SDValue Reg0 = CurDAG->getRegister(0, MVT::i32); 3281 3282 if ((LSB + Width + 1) == N->getValueType(0).getSizeInBits()) { 3283 // It's cheaper to use a right shift to extract the top bits. 3284 if (Subtarget->isThumb()) { 3285 Opc = isSigned ? ARM::t2ASRri : ARM::t2LSRri; 3286 SDValue Ops[] = { N->getOperand(0).getOperand(0), 3287 CurDAG->getTargetConstant(LSB, dl, MVT::i32), 3288 getAL(CurDAG, dl), Reg0, Reg0 }; 3289 CurDAG->SelectNodeTo(N, Opc, MVT::i32, Ops); 3290 return true; 3291 } 3292 3293 // ARM models shift instructions as MOVsi with shifter operand. 3294 ARM_AM::ShiftOpc ShOpcVal = ARM_AM::getShiftOpcForNode(ISD::SRL); 3295 SDValue ShOpc = 3296 CurDAG->getTargetConstant(ARM_AM::getSORegOpc(ShOpcVal, LSB), dl, 3297 MVT::i32); 3298 SDValue Ops[] = { N->getOperand(0).getOperand(0), ShOpc, 3299 getAL(CurDAG, dl), Reg0, Reg0 }; 3300 CurDAG->SelectNodeTo(N, ARM::MOVsi, MVT::i32, Ops); 3301 return true; 3302 } 3303 3304 assert(LSB + Width + 1 <= 32 && "Shouldn't create an invalid ubfx"); 3305 SDValue Ops[] = { N->getOperand(0).getOperand(0), 3306 CurDAG->getTargetConstant(LSB, dl, MVT::i32), 3307 CurDAG->getTargetConstant(Width, dl, MVT::i32), 3308 getAL(CurDAG, dl), Reg0 }; 3309 CurDAG->SelectNodeTo(N, Opc, MVT::i32, Ops); 3310 return true; 3311 } 3312 } 3313 return false; 3314 } 3315 3316 // Otherwise, we're looking for a shift of a shift 3317 unsigned Shl_imm = 0; 3318 if (isOpcWithIntImmediate(N->getOperand(0).getNode(), ISD::SHL, Shl_imm)) { 3319 assert(Shl_imm > 0 && Shl_imm < 32 && "bad amount in shift node!"); 3320 unsigned Srl_imm = 0; 3321 if (isInt32Immediate(N->getOperand(1), Srl_imm)) { 3322 assert(Srl_imm > 0 && Srl_imm < 32 && "bad amount in shift node!"); 3323 // Note: The width operand is encoded as width-1. 3324 unsigned Width = 32 - Srl_imm - 1; 3325 int LSB = Srl_imm - Shl_imm; 3326 if (LSB < 0) 3327 return false; 3328 SDValue Reg0 = CurDAG->getRegister(0, MVT::i32); 3329 assert(LSB + Width + 1 <= 32 && "Shouldn't create an invalid ubfx"); 3330 SDValue Ops[] = { N->getOperand(0).getOperand(0), 3331 CurDAG->getTargetConstant(LSB, dl, MVT::i32), 3332 CurDAG->getTargetConstant(Width, dl, MVT::i32), 3333 getAL(CurDAG, dl), Reg0 }; 3334 CurDAG->SelectNodeTo(N, Opc, MVT::i32, Ops); 3335 return true; 3336 } 3337 } 3338 3339 // Or we are looking for a shift of an and, with a mask operand 3340 if (isOpcWithIntImmediate(N->getOperand(0).getNode(), ISD::AND, And_imm) && 3341 isShiftedMask_32(And_imm)) { 3342 unsigned Srl_imm = 0; 3343 unsigned LSB = countTrailingZeros(And_imm); 3344 // Shift must be the same as the ands lsb 3345 if (isInt32Immediate(N->getOperand(1), Srl_imm) && Srl_imm == LSB) { 3346 assert(Srl_imm > 0 && Srl_imm < 32 && "bad amount in shift node!"); 3347 unsigned MSB = 31 - countLeadingZeros(And_imm); 3348 // Note: The width operand is encoded as width-1. 3349 unsigned Width = MSB - LSB; 3350 SDValue Reg0 = CurDAG->getRegister(0, MVT::i32); 3351 assert(Srl_imm + Width + 1 <= 32 && "Shouldn't create an invalid ubfx"); 3352 SDValue Ops[] = { N->getOperand(0).getOperand(0), 3353 CurDAG->getTargetConstant(Srl_imm, dl, MVT::i32), 3354 CurDAG->getTargetConstant(Width, dl, MVT::i32), 3355 getAL(CurDAG, dl), Reg0 }; 3356 CurDAG->SelectNodeTo(N, Opc, MVT::i32, Ops); 3357 return true; 3358 } 3359 } 3360 3361 if (N->getOpcode() == ISD::SIGN_EXTEND_INREG) { 3362 unsigned Width = cast<VTSDNode>(N->getOperand(1))->getVT().getSizeInBits(); 3363 unsigned LSB = 0; 3364 if (!isOpcWithIntImmediate(N->getOperand(0).getNode(), ISD::SRL, LSB) && 3365 !isOpcWithIntImmediate(N->getOperand(0).getNode(), ISD::SRA, LSB)) 3366 return false; 3367 3368 if (LSB + Width > 32) 3369 return false; 3370 3371 SDValue Reg0 = CurDAG->getRegister(0, MVT::i32); 3372 assert(LSB + Width <= 32 && "Shouldn't create an invalid ubfx"); 3373 SDValue Ops[] = { N->getOperand(0).getOperand(0), 3374 CurDAG->getTargetConstant(LSB, dl, MVT::i32), 3375 CurDAG->getTargetConstant(Width - 1, dl, MVT::i32), 3376 getAL(CurDAG, dl), Reg0 }; 3377 CurDAG->SelectNodeTo(N, Opc, MVT::i32, Ops); 3378 return true; 3379 } 3380 3381 return false; 3382 } 3383 3384 /// Target-specific DAG combining for ISD::XOR. 3385 /// Target-independent combining lowers SELECT_CC nodes of the form 3386 /// select_cc setg[ge] X, 0, X, -X 3387 /// select_cc setgt X, -1, X, -X 3388 /// select_cc setl[te] X, 0, -X, X 3389 /// select_cc setlt X, 1, -X, X 3390 /// which represent Integer ABS into: 3391 /// Y = sra (X, size(X)-1); xor (add (X, Y), Y) 3392 /// ARM instruction selection detects the latter and matches it to 3393 /// ARM::ABS or ARM::t2ABS machine node. 3394 bool ARMDAGToDAGISel::tryABSOp(SDNode *N){ 3395 SDValue XORSrc0 = N->getOperand(0); 3396 SDValue XORSrc1 = N->getOperand(1); 3397 EVT VT = N->getValueType(0); 3398 3399 if (Subtarget->isThumb1Only()) 3400 return false; 3401 3402 if (XORSrc0.getOpcode() != ISD::ADD || XORSrc1.getOpcode() != ISD::SRA) 3403 return false; 3404 3405 SDValue ADDSrc0 = XORSrc0.getOperand(0); 3406 SDValue ADDSrc1 = XORSrc0.getOperand(1); 3407 SDValue SRASrc0 = XORSrc1.getOperand(0); 3408 SDValue SRASrc1 = XORSrc1.getOperand(1); 3409 ConstantSDNode *SRAConstant = dyn_cast<ConstantSDNode>(SRASrc1); 3410 EVT XType = SRASrc0.getValueType(); 3411 unsigned Size = XType.getSizeInBits() - 1; 3412 3413 if (ADDSrc1 == XORSrc1 && ADDSrc0 == SRASrc0 && 3414 XType.isInteger() && SRAConstant != nullptr && 3415 Size == SRAConstant->getZExtValue()) { 3416 unsigned Opcode = Subtarget->isThumb2() ? ARM::t2ABS : ARM::ABS; 3417 CurDAG->SelectNodeTo(N, Opcode, VT, ADDSrc0); 3418 return true; 3419 } 3420 3421 return false; 3422 } 3423 3424 /// We've got special pseudo-instructions for these 3425 void ARMDAGToDAGISel::SelectCMP_SWAP(SDNode *N) { 3426 unsigned Opcode; 3427 EVT MemTy = cast<MemSDNode>(N)->getMemoryVT(); 3428 if (MemTy == MVT::i8) 3429 Opcode = Subtarget->isThumb() ? ARM::tCMP_SWAP_8 : ARM::CMP_SWAP_8; 3430 else if (MemTy == MVT::i16) 3431 Opcode = Subtarget->isThumb() ? ARM::tCMP_SWAP_16 : ARM::CMP_SWAP_16; 3432 else if (MemTy == MVT::i32) 3433 Opcode = ARM::CMP_SWAP_32; 3434 else 3435 llvm_unreachable("Unknown AtomicCmpSwap type"); 3436 3437 SDValue Ops[] = {N->getOperand(1), N->getOperand(2), N->getOperand(3), 3438 N->getOperand(0)}; 3439 SDNode *CmpSwap = CurDAG->getMachineNode( 3440 Opcode, SDLoc(N), 3441 CurDAG->getVTList(MVT::i32, MVT::i32, MVT::Other), Ops); 3442 3443 MachineMemOperand *MemOp = cast<MemSDNode>(N)->getMemOperand(); 3444 CurDAG->setNodeMemRefs(cast<MachineSDNode>(CmpSwap), {MemOp}); 3445 3446 ReplaceUses(SDValue(N, 0), SDValue(CmpSwap, 0)); 3447 ReplaceUses(SDValue(N, 1), SDValue(CmpSwap, 2)); 3448 CurDAG->RemoveDeadNode(N); 3449 } 3450 3451 static Optional<std::pair<unsigned, unsigned>> 3452 getContiguousRangeOfSetBits(const APInt &A) { 3453 unsigned FirstOne = A.getBitWidth() - A.countLeadingZeros() - 1; 3454 unsigned LastOne = A.countTrailingZeros(); 3455 if (A.countPopulation() != (FirstOne - LastOne + 1)) 3456 return Optional<std::pair<unsigned,unsigned>>(); 3457 return std::make_pair(FirstOne, LastOne); 3458 } 3459 3460 void ARMDAGToDAGISel::SelectCMPZ(SDNode *N, bool &SwitchEQNEToPLMI) { 3461 assert(N->getOpcode() == ARMISD::CMPZ); 3462 SwitchEQNEToPLMI = false; 3463 3464 if (!Subtarget->isThumb()) 3465 // FIXME: Work out whether it is profitable to do this in A32 mode - LSL and 3466 // LSR don't exist as standalone instructions - they need the barrel shifter. 3467 return; 3468 3469 // select (cmpz (and X, C), #0) -> (LSLS X) or (LSRS X) or (LSRS (LSLS X)) 3470 SDValue And = N->getOperand(0); 3471 if (!And->hasOneUse()) 3472 return; 3473 3474 SDValue Zero = N->getOperand(1); 3475 if (!isa<ConstantSDNode>(Zero) || !cast<ConstantSDNode>(Zero)->isNullValue() || 3476 And->getOpcode() != ISD::AND) 3477 return; 3478 SDValue X = And.getOperand(0); 3479 auto C = dyn_cast<ConstantSDNode>(And.getOperand(1)); 3480 3481 if (!C) 3482 return; 3483 auto Range = getContiguousRangeOfSetBits(C->getAPIntValue()); 3484 if (!Range) 3485 return; 3486 3487 // There are several ways to lower this: 3488 SDNode *NewN; 3489 SDLoc dl(N); 3490 3491 auto EmitShift = [&](unsigned Opc, SDValue Src, unsigned Imm) -> SDNode* { 3492 if (Subtarget->isThumb2()) { 3493 Opc = (Opc == ARM::tLSLri) ? ARM::t2LSLri : ARM::t2LSRri; 3494 SDValue Ops[] = { Src, CurDAG->getTargetConstant(Imm, dl, MVT::i32), 3495 getAL(CurDAG, dl), CurDAG->getRegister(0, MVT::i32), 3496 CurDAG->getRegister(0, MVT::i32) }; 3497 return CurDAG->getMachineNode(Opc, dl, MVT::i32, Ops); 3498 } else { 3499 SDValue Ops[] = {CurDAG->getRegister(ARM::CPSR, MVT::i32), Src, 3500 CurDAG->getTargetConstant(Imm, dl, MVT::i32), 3501 getAL(CurDAG, dl), CurDAG->getRegister(0, MVT::i32)}; 3502 return CurDAG->getMachineNode(Opc, dl, MVT::i32, Ops); 3503 } 3504 }; 3505 3506 if (Range->second == 0) { 3507 // 1. Mask includes the LSB -> Simply shift the top N bits off 3508 NewN = EmitShift(ARM::tLSLri, X, 31 - Range->first); 3509 ReplaceNode(And.getNode(), NewN); 3510 } else if (Range->first == 31) { 3511 // 2. Mask includes the MSB -> Simply shift the bottom N bits off 3512 NewN = EmitShift(ARM::tLSRri, X, Range->second); 3513 ReplaceNode(And.getNode(), NewN); 3514 } else if (Range->first == Range->second) { 3515 // 3. Only one bit is set. We can shift this into the sign bit and use a 3516 // PL/MI comparison. 3517 NewN = EmitShift(ARM::tLSLri, X, 31 - Range->first); 3518 ReplaceNode(And.getNode(), NewN); 3519 3520 SwitchEQNEToPLMI = true; 3521 } else if (!Subtarget->hasV6T2Ops()) { 3522 // 4. Do a double shift to clear bottom and top bits, but only in 3523 // thumb-1 mode as in thumb-2 we can use UBFX. 3524 NewN = EmitShift(ARM::tLSLri, X, 31 - Range->first); 3525 NewN = EmitShift(ARM::tLSRri, SDValue(NewN, 0), 3526 Range->second + (31 - Range->first)); 3527 ReplaceNode(And.getNode(), NewN); 3528 } 3529 3530 } 3531 3532 void ARMDAGToDAGISel::Select(SDNode *N) { 3533 SDLoc dl(N); 3534 3535 if (N->isMachineOpcode()) { 3536 N->setNodeId(-1); 3537 return; // Already selected. 3538 } 3539 3540 switch (N->getOpcode()) { 3541 default: break; 3542 case ISD::STORE: { 3543 // For Thumb1, match an sp-relative store in C++. This is a little 3544 // unfortunate, but I don't think I can make the chain check work 3545 // otherwise. (The chain of the store has to be the same as the chain 3546 // of the CopyFromReg, or else we can't replace the CopyFromReg with 3547 // a direct reference to "SP".) 3548 // 3549 // This is only necessary on Thumb1 because Thumb1 sp-relative stores use 3550 // a different addressing mode from other four-byte stores. 3551 // 3552 // This pattern usually comes up with call arguments. 3553 StoreSDNode *ST = cast<StoreSDNode>(N); 3554 SDValue Ptr = ST->getBasePtr(); 3555 if (Subtarget->isThumb1Only() && ST->isUnindexed()) { 3556 int RHSC = 0; 3557 if (Ptr.getOpcode() == ISD::ADD && 3558 isScaledConstantInRange(Ptr.getOperand(1), /*Scale=*/4, 0, 256, RHSC)) 3559 Ptr = Ptr.getOperand(0); 3560 3561 if (Ptr.getOpcode() == ISD::CopyFromReg && 3562 cast<RegisterSDNode>(Ptr.getOperand(1))->getReg() == ARM::SP && 3563 Ptr.getOperand(0) == ST->getChain()) { 3564 SDValue Ops[] = {ST->getValue(), 3565 CurDAG->getRegister(ARM::SP, MVT::i32), 3566 CurDAG->getTargetConstant(RHSC, dl, MVT::i32), 3567 getAL(CurDAG, dl), 3568 CurDAG->getRegister(0, MVT::i32), 3569 ST->getChain()}; 3570 MachineSDNode *ResNode = 3571 CurDAG->getMachineNode(ARM::tSTRspi, dl, MVT::Other, Ops); 3572 MachineMemOperand *MemOp = ST->getMemOperand(); 3573 CurDAG->setNodeMemRefs(cast<MachineSDNode>(ResNode), {MemOp}); 3574 ReplaceNode(N, ResNode); 3575 return; 3576 } 3577 } 3578 break; 3579 } 3580 case ISD::WRITE_REGISTER: 3581 if (tryWriteRegister(N)) 3582 return; 3583 break; 3584 case ISD::READ_REGISTER: 3585 if (tryReadRegister(N)) 3586 return; 3587 break; 3588 case ISD::INLINEASM: 3589 case ISD::INLINEASM_BR: 3590 if (tryInlineAsm(N)) 3591 return; 3592 break; 3593 case ISD::XOR: 3594 // Select special operations if XOR node forms integer ABS pattern 3595 if (tryABSOp(N)) 3596 return; 3597 // Other cases are autogenerated. 3598 break; 3599 case ISD::Constant: { 3600 unsigned Val = cast<ConstantSDNode>(N)->getZExtValue(); 3601 // If we can't materialize the constant we need to use a literal pool 3602 if (ConstantMaterializationCost(Val, Subtarget) > 2) { 3603 SDValue CPIdx = CurDAG->getTargetConstantPool( 3604 ConstantInt::get(Type::getInt32Ty(*CurDAG->getContext()), Val), 3605 TLI->getPointerTy(CurDAG->getDataLayout())); 3606 3607 SDNode *ResNode; 3608 if (Subtarget->isThumb()) { 3609 SDValue Ops[] = { 3610 CPIdx, 3611 getAL(CurDAG, dl), 3612 CurDAG->getRegister(0, MVT::i32), 3613 CurDAG->getEntryNode() 3614 }; 3615 ResNode = CurDAG->getMachineNode(ARM::tLDRpci, dl, MVT::i32, MVT::Other, 3616 Ops); 3617 } else { 3618 SDValue Ops[] = { 3619 CPIdx, 3620 CurDAG->getTargetConstant(0, dl, MVT::i32), 3621 getAL(CurDAG, dl), 3622 CurDAG->getRegister(0, MVT::i32), 3623 CurDAG->getEntryNode() 3624 }; 3625 ResNode = CurDAG->getMachineNode(ARM::LDRcp, dl, MVT::i32, MVT::Other, 3626 Ops); 3627 } 3628 // Annotate the Node with memory operand information so that MachineInstr 3629 // queries work properly. This e.g. gives the register allocation the 3630 // required information for rematerialization. 3631 MachineFunction& MF = CurDAG->getMachineFunction(); 3632 MachineMemOperand *MemOp = 3633 MF.getMachineMemOperand(MachinePointerInfo::getConstantPool(MF), 3634 MachineMemOperand::MOLoad, 4, Align(4)); 3635 3636 CurDAG->setNodeMemRefs(cast<MachineSDNode>(ResNode), {MemOp}); 3637 3638 ReplaceNode(N, ResNode); 3639 return; 3640 } 3641 3642 // Other cases are autogenerated. 3643 break; 3644 } 3645 case ISD::FrameIndex: { 3646 // Selects to ADDri FI, 0 which in turn will become ADDri SP, imm. 3647 int FI = cast<FrameIndexSDNode>(N)->getIndex(); 3648 SDValue TFI = CurDAG->getTargetFrameIndex( 3649 FI, TLI->getPointerTy(CurDAG->getDataLayout())); 3650 if (Subtarget->isThumb1Only()) { 3651 // Set the alignment of the frame object to 4, to avoid having to generate 3652 // more than one ADD 3653 MachineFrameInfo &MFI = MF->getFrameInfo(); 3654 if (MFI.getObjectAlign(FI) < Align(4)) 3655 MFI.setObjectAlignment(FI, Align(4)); 3656 CurDAG->SelectNodeTo(N, ARM::tADDframe, MVT::i32, TFI, 3657 CurDAG->getTargetConstant(0, dl, MVT::i32)); 3658 return; 3659 } else { 3660 unsigned Opc = ((Subtarget->isThumb() && Subtarget->hasThumb2()) ? 3661 ARM::t2ADDri : ARM::ADDri); 3662 SDValue Ops[] = { TFI, CurDAG->getTargetConstant(0, dl, MVT::i32), 3663 getAL(CurDAG, dl), CurDAG->getRegister(0, MVT::i32), 3664 CurDAG->getRegister(0, MVT::i32) }; 3665 CurDAG->SelectNodeTo(N, Opc, MVT::i32, Ops); 3666 return; 3667 } 3668 } 3669 case ISD::INSERT_VECTOR_ELT: { 3670 if (tryInsertVectorElt(N)) 3671 return; 3672 break; 3673 } 3674 case ISD::SRL: 3675 if (tryV6T2BitfieldExtractOp(N, false)) 3676 return; 3677 break; 3678 case ISD::SIGN_EXTEND_INREG: 3679 case ISD::SRA: 3680 if (tryV6T2BitfieldExtractOp(N, true)) 3681 return; 3682 break; 3683 case ISD::FMUL: 3684 if (tryFMULFixed(N, dl)) 3685 return; 3686 break; 3687 case ISD::MUL: 3688 if (Subtarget->isThumb1Only()) 3689 break; 3690 if (ConstantSDNode *C = dyn_cast<ConstantSDNode>(N->getOperand(1))) { 3691 unsigned RHSV = C->getZExtValue(); 3692 if (!RHSV) break; 3693 if (isPowerOf2_32(RHSV-1)) { // 2^n+1? 3694 unsigned ShImm = Log2_32(RHSV-1); 3695 if (ShImm >= 32) 3696 break; 3697 SDValue V = N->getOperand(0); 3698 ShImm = ARM_AM::getSORegOpc(ARM_AM::lsl, ShImm); 3699 SDValue ShImmOp = CurDAG->getTargetConstant(ShImm, dl, MVT::i32); 3700 SDValue Reg0 = CurDAG->getRegister(0, MVT::i32); 3701 if (Subtarget->isThumb()) { 3702 SDValue Ops[] = { V, V, ShImmOp, getAL(CurDAG, dl), Reg0, Reg0 }; 3703 CurDAG->SelectNodeTo(N, ARM::t2ADDrs, MVT::i32, Ops); 3704 return; 3705 } else { 3706 SDValue Ops[] = { V, V, Reg0, ShImmOp, getAL(CurDAG, dl), Reg0, 3707 Reg0 }; 3708 CurDAG->SelectNodeTo(N, ARM::ADDrsi, MVT::i32, Ops); 3709 return; 3710 } 3711 } 3712 if (isPowerOf2_32(RHSV+1)) { // 2^n-1? 3713 unsigned ShImm = Log2_32(RHSV+1); 3714 if (ShImm >= 32) 3715 break; 3716 SDValue V = N->getOperand(0); 3717 ShImm = ARM_AM::getSORegOpc(ARM_AM::lsl, ShImm); 3718 SDValue ShImmOp = CurDAG->getTargetConstant(ShImm, dl, MVT::i32); 3719 SDValue Reg0 = CurDAG->getRegister(0, MVT::i32); 3720 if (Subtarget->isThumb()) { 3721 SDValue Ops[] = { V, V, ShImmOp, getAL(CurDAG, dl), Reg0, Reg0 }; 3722 CurDAG->SelectNodeTo(N, ARM::t2RSBrs, MVT::i32, Ops); 3723 return; 3724 } else { 3725 SDValue Ops[] = { V, V, Reg0, ShImmOp, getAL(CurDAG, dl), Reg0, 3726 Reg0 }; 3727 CurDAG->SelectNodeTo(N, ARM::RSBrsi, MVT::i32, Ops); 3728 return; 3729 } 3730 } 3731 } 3732 break; 3733 case ISD::AND: { 3734 // Check for unsigned bitfield extract 3735 if (tryV6T2BitfieldExtractOp(N, false)) 3736 return; 3737 3738 // If an immediate is used in an AND node, it is possible that the immediate 3739 // can be more optimally materialized when negated. If this is the case we 3740 // can negate the immediate and use a BIC instead. 3741 auto *N1C = dyn_cast<ConstantSDNode>(N->getOperand(1)); 3742 if (N1C && N1C->hasOneUse() && Subtarget->isThumb()) { 3743 uint32_t Imm = (uint32_t) N1C->getZExtValue(); 3744 3745 // In Thumb2 mode, an AND can take a 12-bit immediate. If this 3746 // immediate can be negated and fit in the immediate operand of 3747 // a t2BIC, don't do any manual transform here as this can be 3748 // handled by the generic ISel machinery. 3749 bool PreferImmediateEncoding = 3750 Subtarget->hasThumb2() && (is_t2_so_imm(Imm) || is_t2_so_imm_not(Imm)); 3751 if (!PreferImmediateEncoding && 3752 ConstantMaterializationCost(Imm, Subtarget) > 3753 ConstantMaterializationCost(~Imm, Subtarget)) { 3754 // The current immediate costs more to materialize than a negated 3755 // immediate, so negate the immediate and use a BIC. 3756 SDValue NewImm = 3757 CurDAG->getConstant(~N1C->getZExtValue(), dl, MVT::i32); 3758 // If the new constant didn't exist before, reposition it in the topological 3759 // ordering so it is just before N. Otherwise, don't touch its location. 3760 if (NewImm->getNodeId() == -1) 3761 CurDAG->RepositionNode(N->getIterator(), NewImm.getNode()); 3762 3763 if (!Subtarget->hasThumb2()) { 3764 SDValue Ops[] = {CurDAG->getRegister(ARM::CPSR, MVT::i32), 3765 N->getOperand(0), NewImm, getAL(CurDAG, dl), 3766 CurDAG->getRegister(0, MVT::i32)}; 3767 ReplaceNode(N, CurDAG->getMachineNode(ARM::tBIC, dl, MVT::i32, Ops)); 3768 return; 3769 } else { 3770 SDValue Ops[] = {N->getOperand(0), NewImm, getAL(CurDAG, dl), 3771 CurDAG->getRegister(0, MVT::i32), 3772 CurDAG->getRegister(0, MVT::i32)}; 3773 ReplaceNode(N, 3774 CurDAG->getMachineNode(ARM::t2BICrr, dl, MVT::i32, Ops)); 3775 return; 3776 } 3777 } 3778 } 3779 3780 // (and (or x, c2), c1) and top 16-bits of c1 and c2 match, lower 16-bits 3781 // of c1 are 0xffff, and lower 16-bit of c2 are 0. That is, the top 16-bits 3782 // are entirely contributed by c2 and lower 16-bits are entirely contributed 3783 // by x. That's equal to (or (and x, 0xffff), (and c1, 0xffff0000)). 3784 // Select it to: "movt x, ((c1 & 0xffff) >> 16) 3785 EVT VT = N->getValueType(0); 3786 if (VT != MVT::i32) 3787 break; 3788 unsigned Opc = (Subtarget->isThumb() && Subtarget->hasThumb2()) 3789 ? ARM::t2MOVTi16 3790 : (Subtarget->hasV6T2Ops() ? ARM::MOVTi16 : 0); 3791 if (!Opc) 3792 break; 3793 SDValue N0 = N->getOperand(0), N1 = N->getOperand(1); 3794 N1C = dyn_cast<ConstantSDNode>(N1); 3795 if (!N1C) 3796 break; 3797 if (N0.getOpcode() == ISD::OR && N0.getNode()->hasOneUse()) { 3798 SDValue N2 = N0.getOperand(1); 3799 ConstantSDNode *N2C = dyn_cast<ConstantSDNode>(N2); 3800 if (!N2C) 3801 break; 3802 unsigned N1CVal = N1C->getZExtValue(); 3803 unsigned N2CVal = N2C->getZExtValue(); 3804 if ((N1CVal & 0xffff0000U) == (N2CVal & 0xffff0000U) && 3805 (N1CVal & 0xffffU) == 0xffffU && 3806 (N2CVal & 0xffffU) == 0x0U) { 3807 SDValue Imm16 = CurDAG->getTargetConstant((N2CVal & 0xFFFF0000U) >> 16, 3808 dl, MVT::i32); 3809 SDValue Ops[] = { N0.getOperand(0), Imm16, 3810 getAL(CurDAG, dl), CurDAG->getRegister(0, MVT::i32) }; 3811 ReplaceNode(N, CurDAG->getMachineNode(Opc, dl, VT, Ops)); 3812 return; 3813 } 3814 } 3815 3816 break; 3817 } 3818 case ARMISD::UMAAL: { 3819 unsigned Opc = Subtarget->isThumb() ? ARM::t2UMAAL : ARM::UMAAL; 3820 SDValue Ops[] = { N->getOperand(0), N->getOperand(1), 3821 N->getOperand(2), N->getOperand(3), 3822 getAL(CurDAG, dl), 3823 CurDAG->getRegister(0, MVT::i32) }; 3824 ReplaceNode(N, CurDAG->getMachineNode(Opc, dl, MVT::i32, MVT::i32, Ops)); 3825 return; 3826 } 3827 case ARMISD::UMLAL:{ 3828 if (Subtarget->isThumb()) { 3829 SDValue Ops[] = { N->getOperand(0), N->getOperand(1), N->getOperand(2), 3830 N->getOperand(3), getAL(CurDAG, dl), 3831 CurDAG->getRegister(0, MVT::i32)}; 3832 ReplaceNode( 3833 N, CurDAG->getMachineNode(ARM::t2UMLAL, dl, MVT::i32, MVT::i32, Ops)); 3834 return; 3835 }else{ 3836 SDValue Ops[] = { N->getOperand(0), N->getOperand(1), N->getOperand(2), 3837 N->getOperand(3), getAL(CurDAG, dl), 3838 CurDAG->getRegister(0, MVT::i32), 3839 CurDAG->getRegister(0, MVT::i32) }; 3840 ReplaceNode(N, CurDAG->getMachineNode( 3841 Subtarget->hasV6Ops() ? ARM::UMLAL : ARM::UMLALv5, dl, 3842 MVT::i32, MVT::i32, Ops)); 3843 return; 3844 } 3845 } 3846 case ARMISD::SMLAL:{ 3847 if (Subtarget->isThumb()) { 3848 SDValue Ops[] = { N->getOperand(0), N->getOperand(1), N->getOperand(2), 3849 N->getOperand(3), getAL(CurDAG, dl), 3850 CurDAG->getRegister(0, MVT::i32)}; 3851 ReplaceNode( 3852 N, CurDAG->getMachineNode(ARM::t2SMLAL, dl, MVT::i32, MVT::i32, Ops)); 3853 return; 3854 }else{ 3855 SDValue Ops[] = { N->getOperand(0), N->getOperand(1), N->getOperand(2), 3856 N->getOperand(3), getAL(CurDAG, dl), 3857 CurDAG->getRegister(0, MVT::i32), 3858 CurDAG->getRegister(0, MVT::i32) }; 3859 ReplaceNode(N, CurDAG->getMachineNode( 3860 Subtarget->hasV6Ops() ? ARM::SMLAL : ARM::SMLALv5, dl, 3861 MVT::i32, MVT::i32, Ops)); 3862 return; 3863 } 3864 } 3865 case ARMISD::SUBE: { 3866 if (!Subtarget->hasV6Ops() || !Subtarget->hasDSP()) 3867 break; 3868 // Look for a pattern to match SMMLS 3869 // (sube a, (smul_loHi a, b), (subc 0, (smul_LOhi(a, b)))) 3870 if (N->getOperand(1).getOpcode() != ISD::SMUL_LOHI || 3871 N->getOperand(2).getOpcode() != ARMISD::SUBC || 3872 !SDValue(N, 1).use_empty()) 3873 break; 3874 3875 if (Subtarget->isThumb()) 3876 assert(Subtarget->hasThumb2() && 3877 "This pattern should not be generated for Thumb"); 3878 3879 SDValue SmulLoHi = N->getOperand(1); 3880 SDValue Subc = N->getOperand(2); 3881 auto *Zero = dyn_cast<ConstantSDNode>(Subc.getOperand(0)); 3882 3883 if (!Zero || Zero->getZExtValue() != 0 || 3884 Subc.getOperand(1) != SmulLoHi.getValue(0) || 3885 N->getOperand(1) != SmulLoHi.getValue(1) || 3886 N->getOperand(2) != Subc.getValue(1)) 3887 break; 3888 3889 unsigned Opc = Subtarget->isThumb2() ? ARM::t2SMMLS : ARM::SMMLS; 3890 SDValue Ops[] = { SmulLoHi.getOperand(0), SmulLoHi.getOperand(1), 3891 N->getOperand(0), getAL(CurDAG, dl), 3892 CurDAG->getRegister(0, MVT::i32) }; 3893 ReplaceNode(N, CurDAG->getMachineNode(Opc, dl, MVT::i32, Ops)); 3894 return; 3895 } 3896 case ISD::LOAD: { 3897 if (Subtarget->hasMVEIntegerOps() && tryMVEIndexedLoad(N)) 3898 return; 3899 if (Subtarget->isThumb() && Subtarget->hasThumb2()) { 3900 if (tryT2IndexedLoad(N)) 3901 return; 3902 } else if (Subtarget->isThumb()) { 3903 if (tryT1IndexedLoad(N)) 3904 return; 3905 } else if (tryARMIndexedLoad(N)) 3906 return; 3907 // Other cases are autogenerated. 3908 break; 3909 } 3910 case ISD::MLOAD: 3911 if (Subtarget->hasMVEIntegerOps() && tryMVEIndexedLoad(N)) 3912 return; 3913 // Other cases are autogenerated. 3914 break; 3915 case ARMISD::WLSSETUP: { 3916 SDNode *New = CurDAG->getMachineNode(ARM::t2WhileLoopSetup, dl, MVT::i32, 3917 N->getOperand(0)); 3918 ReplaceUses(N, New); 3919 CurDAG->RemoveDeadNode(N); 3920 return; 3921 } 3922 case ARMISD::WLS: { 3923 SDNode *New = CurDAG->getMachineNode(ARM::t2WhileLoopStart, dl, MVT::Other, 3924 N->getOperand(1), N->getOperand(2), 3925 N->getOperand(0)); 3926 ReplaceUses(N, New); 3927 CurDAG->RemoveDeadNode(N); 3928 return; 3929 } 3930 case ARMISD::LE: { 3931 SDValue Ops[] = { N->getOperand(1), 3932 N->getOperand(2), 3933 N->getOperand(0) }; 3934 unsigned Opc = ARM::t2LoopEnd; 3935 SDNode *New = CurDAG->getMachineNode(Opc, dl, MVT::Other, Ops); 3936 ReplaceUses(N, New); 3937 CurDAG->RemoveDeadNode(N); 3938 return; 3939 } 3940 case ARMISD::LDRD: { 3941 if (Subtarget->isThumb2()) 3942 break; // TableGen handles isel in this case. 3943 SDValue Base, RegOffset, ImmOffset; 3944 const SDValue &Chain = N->getOperand(0); 3945 const SDValue &Addr = N->getOperand(1); 3946 SelectAddrMode3(Addr, Base, RegOffset, ImmOffset); 3947 if (RegOffset != CurDAG->getRegister(0, MVT::i32)) { 3948 // The register-offset variant of LDRD mandates that the register 3949 // allocated to RegOffset is not reused in any of the remaining operands. 3950 // This restriction is currently not enforced. Therefore emitting this 3951 // variant is explicitly avoided. 3952 Base = Addr; 3953 RegOffset = CurDAG->getRegister(0, MVT::i32); 3954 } 3955 SDValue Ops[] = {Base, RegOffset, ImmOffset, Chain}; 3956 SDNode *New = CurDAG->getMachineNode(ARM::LOADDUAL, dl, 3957 {MVT::Untyped, MVT::Other}, Ops); 3958 SDValue Lo = CurDAG->getTargetExtractSubreg(ARM::gsub_0, dl, MVT::i32, 3959 SDValue(New, 0)); 3960 SDValue Hi = CurDAG->getTargetExtractSubreg(ARM::gsub_1, dl, MVT::i32, 3961 SDValue(New, 0)); 3962 transferMemOperands(N, New); 3963 ReplaceUses(SDValue(N, 0), Lo); 3964 ReplaceUses(SDValue(N, 1), Hi); 3965 ReplaceUses(SDValue(N, 2), SDValue(New, 1)); 3966 CurDAG->RemoveDeadNode(N); 3967 return; 3968 } 3969 case ARMISD::STRD: { 3970 if (Subtarget->isThumb2()) 3971 break; // TableGen handles isel in this case. 3972 SDValue Base, RegOffset, ImmOffset; 3973 const SDValue &Chain = N->getOperand(0); 3974 const SDValue &Addr = N->getOperand(3); 3975 SelectAddrMode3(Addr, Base, RegOffset, ImmOffset); 3976 if (RegOffset != CurDAG->getRegister(0, MVT::i32)) { 3977 // The register-offset variant of STRD mandates that the register 3978 // allocated to RegOffset is not reused in any of the remaining operands. 3979 // This restriction is currently not enforced. Therefore emitting this 3980 // variant is explicitly avoided. 3981 Base = Addr; 3982 RegOffset = CurDAG->getRegister(0, MVT::i32); 3983 } 3984 SDNode *RegPair = 3985 createGPRPairNode(MVT::Untyped, N->getOperand(1), N->getOperand(2)); 3986 SDValue Ops[] = {SDValue(RegPair, 0), Base, RegOffset, ImmOffset, Chain}; 3987 SDNode *New = CurDAG->getMachineNode(ARM::STOREDUAL, dl, MVT::Other, Ops); 3988 transferMemOperands(N, New); 3989 ReplaceUses(SDValue(N, 0), SDValue(New, 0)); 3990 CurDAG->RemoveDeadNode(N); 3991 return; 3992 } 3993 case ARMISD::LOOP_DEC: { 3994 SDValue Ops[] = { N->getOperand(1), 3995 N->getOperand(2), 3996 N->getOperand(0) }; 3997 SDNode *Dec = 3998 CurDAG->getMachineNode(ARM::t2LoopDec, dl, 3999 CurDAG->getVTList(MVT::i32, MVT::Other), Ops); 4000 ReplaceUses(N, Dec); 4001 CurDAG->RemoveDeadNode(N); 4002 return; 4003 } 4004 case ARMISD::BRCOND: { 4005 // Pattern: (ARMbrcond:void (bb:Other):$dst, (imm:i32):$cc) 4006 // Emits: (Bcc:void (bb:Other):$dst, (imm:i32):$cc) 4007 // Pattern complexity = 6 cost = 1 size = 0 4008 4009 // Pattern: (ARMbrcond:void (bb:Other):$dst, (imm:i32):$cc) 4010 // Emits: (tBcc:void (bb:Other):$dst, (imm:i32):$cc) 4011 // Pattern complexity = 6 cost = 1 size = 0 4012 4013 // Pattern: (ARMbrcond:void (bb:Other):$dst, (imm:i32):$cc) 4014 // Emits: (t2Bcc:void (bb:Other):$dst, (imm:i32):$cc) 4015 // Pattern complexity = 6 cost = 1 size = 0 4016 4017 unsigned Opc = Subtarget->isThumb() ? 4018 ((Subtarget->hasThumb2()) ? ARM::t2Bcc : ARM::tBcc) : ARM::Bcc; 4019 SDValue Chain = N->getOperand(0); 4020 SDValue N1 = N->getOperand(1); 4021 SDValue N2 = N->getOperand(2); 4022 SDValue N3 = N->getOperand(3); 4023 SDValue InFlag = N->getOperand(4); 4024 assert(N1.getOpcode() == ISD::BasicBlock); 4025 assert(N2.getOpcode() == ISD::Constant); 4026 assert(N3.getOpcode() == ISD::Register); 4027 4028 unsigned CC = (unsigned) cast<ConstantSDNode>(N2)->getZExtValue(); 4029 4030 if (InFlag.getOpcode() == ARMISD::CMPZ) { 4031 if (InFlag.getOperand(0).getOpcode() == ISD::INTRINSIC_W_CHAIN) { 4032 SDValue Int = InFlag.getOperand(0); 4033 uint64_t ID = cast<ConstantSDNode>(Int->getOperand(1))->getZExtValue(); 4034 4035 // Handle low-overhead loops. 4036 if (ID == Intrinsic::loop_decrement_reg) { 4037 SDValue Elements = Int.getOperand(2); 4038 SDValue Size = CurDAG->getTargetConstant( 4039 cast<ConstantSDNode>(Int.getOperand(3))->getZExtValue(), dl, 4040 MVT::i32); 4041 4042 SDValue Args[] = { Elements, Size, Int.getOperand(0) }; 4043 SDNode *LoopDec = 4044 CurDAG->getMachineNode(ARM::t2LoopDec, dl, 4045 CurDAG->getVTList(MVT::i32, MVT::Other), 4046 Args); 4047 ReplaceUses(Int.getNode(), LoopDec); 4048 4049 SDValue EndArgs[] = { SDValue(LoopDec, 0), N1, Chain }; 4050 SDNode *LoopEnd = 4051 CurDAG->getMachineNode(ARM::t2LoopEnd, dl, MVT::Other, EndArgs); 4052 4053 ReplaceUses(N, LoopEnd); 4054 CurDAG->RemoveDeadNode(N); 4055 CurDAG->RemoveDeadNode(InFlag.getNode()); 4056 CurDAG->RemoveDeadNode(Int.getNode()); 4057 return; 4058 } 4059 } 4060 4061 bool SwitchEQNEToPLMI; 4062 SelectCMPZ(InFlag.getNode(), SwitchEQNEToPLMI); 4063 InFlag = N->getOperand(4); 4064 4065 if (SwitchEQNEToPLMI) { 4066 switch ((ARMCC::CondCodes)CC) { 4067 default: llvm_unreachable("CMPZ must be either NE or EQ!"); 4068 case ARMCC::NE: 4069 CC = (unsigned)ARMCC::MI; 4070 break; 4071 case ARMCC::EQ: 4072 CC = (unsigned)ARMCC::PL; 4073 break; 4074 } 4075 } 4076 } 4077 4078 SDValue Tmp2 = CurDAG->getTargetConstant(CC, dl, MVT::i32); 4079 SDValue Ops[] = { N1, Tmp2, N3, Chain, InFlag }; 4080 SDNode *ResNode = CurDAG->getMachineNode(Opc, dl, MVT::Other, 4081 MVT::Glue, Ops); 4082 Chain = SDValue(ResNode, 0); 4083 if (N->getNumValues() == 2) { 4084 InFlag = SDValue(ResNode, 1); 4085 ReplaceUses(SDValue(N, 1), InFlag); 4086 } 4087 ReplaceUses(SDValue(N, 0), 4088 SDValue(Chain.getNode(), Chain.getResNo())); 4089 CurDAG->RemoveDeadNode(N); 4090 return; 4091 } 4092 4093 case ARMISD::CMPZ: { 4094 // select (CMPZ X, #-C) -> (CMPZ (ADDS X, #C), #0) 4095 // This allows us to avoid materializing the expensive negative constant. 4096 // The CMPZ #0 is useless and will be peepholed away but we need to keep it 4097 // for its glue output. 4098 SDValue X = N->getOperand(0); 4099 auto *C = dyn_cast<ConstantSDNode>(N->getOperand(1).getNode()); 4100 if (C && C->getSExtValue() < 0 && Subtarget->isThumb()) { 4101 int64_t Addend = -C->getSExtValue(); 4102 4103 SDNode *Add = nullptr; 4104 // ADDS can be better than CMN if the immediate fits in a 4105 // 16-bit ADDS, which means either [0,256) for tADDi8 or [0,8) for tADDi3. 4106 // Outside that range we can just use a CMN which is 32-bit but has a 4107 // 12-bit immediate range. 4108 if (Addend < 1<<8) { 4109 if (Subtarget->isThumb2()) { 4110 SDValue Ops[] = { X, CurDAG->getTargetConstant(Addend, dl, MVT::i32), 4111 getAL(CurDAG, dl), CurDAG->getRegister(0, MVT::i32), 4112 CurDAG->getRegister(0, MVT::i32) }; 4113 Add = CurDAG->getMachineNode(ARM::t2ADDri, dl, MVT::i32, Ops); 4114 } else { 4115 unsigned Opc = (Addend < 1<<3) ? ARM::tADDi3 : ARM::tADDi8; 4116 SDValue Ops[] = {CurDAG->getRegister(ARM::CPSR, MVT::i32), X, 4117 CurDAG->getTargetConstant(Addend, dl, MVT::i32), 4118 getAL(CurDAG, dl), CurDAG->getRegister(0, MVT::i32)}; 4119 Add = CurDAG->getMachineNode(Opc, dl, MVT::i32, Ops); 4120 } 4121 } 4122 if (Add) { 4123 SDValue Ops2[] = {SDValue(Add, 0), CurDAG->getConstant(0, dl, MVT::i32)}; 4124 CurDAG->MorphNodeTo(N, ARMISD::CMPZ, CurDAG->getVTList(MVT::Glue), Ops2); 4125 } 4126 } 4127 // Other cases are autogenerated. 4128 break; 4129 } 4130 4131 case ARMISD::CMOV: { 4132 SDValue InFlag = N->getOperand(4); 4133 4134 if (InFlag.getOpcode() == ARMISD::CMPZ) { 4135 bool SwitchEQNEToPLMI; 4136 SelectCMPZ(InFlag.getNode(), SwitchEQNEToPLMI); 4137 4138 if (SwitchEQNEToPLMI) { 4139 SDValue ARMcc = N->getOperand(2); 4140 ARMCC::CondCodes CC = 4141 (ARMCC::CondCodes)cast<ConstantSDNode>(ARMcc)->getZExtValue(); 4142 4143 switch (CC) { 4144 default: llvm_unreachable("CMPZ must be either NE or EQ!"); 4145 case ARMCC::NE: 4146 CC = ARMCC::MI; 4147 break; 4148 case ARMCC::EQ: 4149 CC = ARMCC::PL; 4150 break; 4151 } 4152 SDValue NewARMcc = CurDAG->getConstant((unsigned)CC, dl, MVT::i32); 4153 SDValue Ops[] = {N->getOperand(0), N->getOperand(1), NewARMcc, 4154 N->getOperand(3), N->getOperand(4)}; 4155 CurDAG->MorphNodeTo(N, ARMISD::CMOV, N->getVTList(), Ops); 4156 } 4157 4158 } 4159 // Other cases are autogenerated. 4160 break; 4161 } 4162 4163 case ARMISD::VZIP: { 4164 unsigned Opc = 0; 4165 EVT VT = N->getValueType(0); 4166 switch (VT.getSimpleVT().SimpleTy) { 4167 default: return; 4168 case MVT::v8i8: Opc = ARM::VZIPd8; break; 4169 case MVT::v4f16: 4170 case MVT::v4i16: Opc = ARM::VZIPd16; break; 4171 case MVT::v2f32: 4172 // vzip.32 Dd, Dm is a pseudo-instruction expanded to vtrn.32 Dd, Dm. 4173 case MVT::v2i32: Opc = ARM::VTRNd32; break; 4174 case MVT::v16i8: Opc = ARM::VZIPq8; break; 4175 case MVT::v8f16: 4176 case MVT::v8i16: Opc = ARM::VZIPq16; break; 4177 case MVT::v4f32: 4178 case MVT::v4i32: Opc = ARM::VZIPq32; break; 4179 } 4180 SDValue Pred = getAL(CurDAG, dl); 4181 SDValue PredReg = CurDAG->getRegister(0, MVT::i32); 4182 SDValue Ops[] = { N->getOperand(0), N->getOperand(1), Pred, PredReg }; 4183 ReplaceNode(N, CurDAG->getMachineNode(Opc, dl, VT, VT, Ops)); 4184 return; 4185 } 4186 case ARMISD::VUZP: { 4187 unsigned Opc = 0; 4188 EVT VT = N->getValueType(0); 4189 switch (VT.getSimpleVT().SimpleTy) { 4190 default: return; 4191 case MVT::v8i8: Opc = ARM::VUZPd8; break; 4192 case MVT::v4f16: 4193 case MVT::v4i16: Opc = ARM::VUZPd16; break; 4194 case MVT::v2f32: 4195 // vuzp.32 Dd, Dm is a pseudo-instruction expanded to vtrn.32 Dd, Dm. 4196 case MVT::v2i32: Opc = ARM::VTRNd32; break; 4197 case MVT::v16i8: Opc = ARM::VUZPq8; break; 4198 case MVT::v8f16: 4199 case MVT::v8i16: Opc = ARM::VUZPq16; break; 4200 case MVT::v4f32: 4201 case MVT::v4i32: Opc = ARM::VUZPq32; break; 4202 } 4203 SDValue Pred = getAL(CurDAG, dl); 4204 SDValue PredReg = CurDAG->getRegister(0, MVT::i32); 4205 SDValue Ops[] = { N->getOperand(0), N->getOperand(1), Pred, PredReg }; 4206 ReplaceNode(N, CurDAG->getMachineNode(Opc, dl, VT, VT, Ops)); 4207 return; 4208 } 4209 case ARMISD::VTRN: { 4210 unsigned Opc = 0; 4211 EVT VT = N->getValueType(0); 4212 switch (VT.getSimpleVT().SimpleTy) { 4213 default: return; 4214 case MVT::v8i8: Opc = ARM::VTRNd8; break; 4215 case MVT::v4f16: 4216 case MVT::v4i16: Opc = ARM::VTRNd16; break; 4217 case MVT::v2f32: 4218 case MVT::v2i32: Opc = ARM::VTRNd32; break; 4219 case MVT::v16i8: Opc = ARM::VTRNq8; break; 4220 case MVT::v8f16: 4221 case MVT::v8i16: Opc = ARM::VTRNq16; break; 4222 case MVT::v4f32: 4223 case MVT::v4i32: Opc = ARM::VTRNq32; break; 4224 } 4225 SDValue Pred = getAL(CurDAG, dl); 4226 SDValue PredReg = CurDAG->getRegister(0, MVT::i32); 4227 SDValue Ops[] = { N->getOperand(0), N->getOperand(1), Pred, PredReg }; 4228 ReplaceNode(N, CurDAG->getMachineNode(Opc, dl, VT, VT, Ops)); 4229 return; 4230 } 4231 case ARMISD::BUILD_VECTOR: { 4232 EVT VecVT = N->getValueType(0); 4233 EVT EltVT = VecVT.getVectorElementType(); 4234 unsigned NumElts = VecVT.getVectorNumElements(); 4235 if (EltVT == MVT::f64) { 4236 assert(NumElts == 2 && "unexpected type for BUILD_VECTOR"); 4237 ReplaceNode( 4238 N, createDRegPairNode(VecVT, N->getOperand(0), N->getOperand(1))); 4239 return; 4240 } 4241 assert(EltVT == MVT::f32 && "unexpected type for BUILD_VECTOR"); 4242 if (NumElts == 2) { 4243 ReplaceNode( 4244 N, createSRegPairNode(VecVT, N->getOperand(0), N->getOperand(1))); 4245 return; 4246 } 4247 assert(NumElts == 4 && "unexpected type for BUILD_VECTOR"); 4248 ReplaceNode(N, 4249 createQuadSRegsNode(VecVT, N->getOperand(0), N->getOperand(1), 4250 N->getOperand(2), N->getOperand(3))); 4251 return; 4252 } 4253 4254 case ARMISD::VLD1DUP: { 4255 static const uint16_t DOpcodes[] = { ARM::VLD1DUPd8, ARM::VLD1DUPd16, 4256 ARM::VLD1DUPd32 }; 4257 static const uint16_t QOpcodes[] = { ARM::VLD1DUPq8, ARM::VLD1DUPq16, 4258 ARM::VLD1DUPq32 }; 4259 SelectVLDDup(N, /* IsIntrinsic= */ false, false, 1, DOpcodes, QOpcodes); 4260 return; 4261 } 4262 4263 case ARMISD::VLD2DUP: { 4264 static const uint16_t Opcodes[] = { ARM::VLD2DUPd8, ARM::VLD2DUPd16, 4265 ARM::VLD2DUPd32 }; 4266 SelectVLDDup(N, /* IsIntrinsic= */ false, false, 2, Opcodes); 4267 return; 4268 } 4269 4270 case ARMISD::VLD3DUP: { 4271 static const uint16_t Opcodes[] = { ARM::VLD3DUPd8Pseudo, 4272 ARM::VLD3DUPd16Pseudo, 4273 ARM::VLD3DUPd32Pseudo }; 4274 SelectVLDDup(N, /* IsIntrinsic= */ false, false, 3, Opcodes); 4275 return; 4276 } 4277 4278 case ARMISD::VLD4DUP: { 4279 static const uint16_t Opcodes[] = { ARM::VLD4DUPd8Pseudo, 4280 ARM::VLD4DUPd16Pseudo, 4281 ARM::VLD4DUPd32Pseudo }; 4282 SelectVLDDup(N, /* IsIntrinsic= */ false, false, 4, Opcodes); 4283 return; 4284 } 4285 4286 case ARMISD::VLD1DUP_UPD: { 4287 static const uint16_t DOpcodes[] = { ARM::VLD1DUPd8wb_fixed, 4288 ARM::VLD1DUPd16wb_fixed, 4289 ARM::VLD1DUPd32wb_fixed }; 4290 static const uint16_t QOpcodes[] = { ARM::VLD1DUPq8wb_fixed, 4291 ARM::VLD1DUPq16wb_fixed, 4292 ARM::VLD1DUPq32wb_fixed }; 4293 SelectVLDDup(N, /* IsIntrinsic= */ false, true, 1, DOpcodes, QOpcodes); 4294 return; 4295 } 4296 4297 case ARMISD::VLD2DUP_UPD: { 4298 static const uint16_t DOpcodes[] = { ARM::VLD2DUPd8wb_fixed, 4299 ARM::VLD2DUPd16wb_fixed, 4300 ARM::VLD2DUPd32wb_fixed, 4301 ARM::VLD1q64wb_fixed }; 4302 static const uint16_t QOpcodes0[] = { ARM::VLD2DUPq8EvenPseudo, 4303 ARM::VLD2DUPq16EvenPseudo, 4304 ARM::VLD2DUPq32EvenPseudo }; 4305 static const uint16_t QOpcodes1[] = { ARM::VLD2DUPq8OddPseudoWB_fixed, 4306 ARM::VLD2DUPq16OddPseudoWB_fixed, 4307 ARM::VLD2DUPq32OddPseudoWB_fixed }; 4308 SelectVLDDup(N, /* IsIntrinsic= */ false, true, 2, DOpcodes, QOpcodes0, QOpcodes1); 4309 return; 4310 } 4311 4312 case ARMISD::VLD3DUP_UPD: { 4313 static const uint16_t DOpcodes[] = { ARM::VLD3DUPd8Pseudo_UPD, 4314 ARM::VLD3DUPd16Pseudo_UPD, 4315 ARM::VLD3DUPd32Pseudo_UPD, 4316 ARM::VLD1d64TPseudoWB_fixed }; 4317 static const uint16_t QOpcodes0[] = { ARM::VLD3DUPq8EvenPseudo, 4318 ARM::VLD3DUPq16EvenPseudo, 4319 ARM::VLD3DUPq32EvenPseudo }; 4320 static const uint16_t QOpcodes1[] = { ARM::VLD3DUPq8OddPseudo_UPD, 4321 ARM::VLD3DUPq16OddPseudo_UPD, 4322 ARM::VLD3DUPq32OddPseudo_UPD }; 4323 SelectVLDDup(N, /* IsIntrinsic= */ false, true, 3, DOpcodes, QOpcodes0, QOpcodes1); 4324 return; 4325 } 4326 4327 case ARMISD::VLD4DUP_UPD: { 4328 static const uint16_t DOpcodes[] = { ARM::VLD4DUPd8Pseudo_UPD, 4329 ARM::VLD4DUPd16Pseudo_UPD, 4330 ARM::VLD4DUPd32Pseudo_UPD, 4331 ARM::VLD1d64QPseudoWB_fixed }; 4332 static const uint16_t QOpcodes0[] = { ARM::VLD4DUPq8EvenPseudo, 4333 ARM::VLD4DUPq16EvenPseudo, 4334 ARM::VLD4DUPq32EvenPseudo }; 4335 static const uint16_t QOpcodes1[] = { ARM::VLD4DUPq8OddPseudo_UPD, 4336 ARM::VLD4DUPq16OddPseudo_UPD, 4337 ARM::VLD4DUPq32OddPseudo_UPD }; 4338 SelectVLDDup(N, /* IsIntrinsic= */ false, true, 4, DOpcodes, QOpcodes0, QOpcodes1); 4339 return; 4340 } 4341 4342 case ARMISD::VLD1_UPD: { 4343 static const uint16_t DOpcodes[] = { ARM::VLD1d8wb_fixed, 4344 ARM::VLD1d16wb_fixed, 4345 ARM::VLD1d32wb_fixed, 4346 ARM::VLD1d64wb_fixed }; 4347 static const uint16_t QOpcodes[] = { ARM::VLD1q8wb_fixed, 4348 ARM::VLD1q16wb_fixed, 4349 ARM::VLD1q32wb_fixed, 4350 ARM::VLD1q64wb_fixed }; 4351 SelectVLD(N, true, 1, DOpcodes, QOpcodes, nullptr); 4352 return; 4353 } 4354 4355 case ARMISD::VLD2_UPD: { 4356 if (Subtarget->hasNEON()) { 4357 static const uint16_t DOpcodes[] = { 4358 ARM::VLD2d8wb_fixed, ARM::VLD2d16wb_fixed, ARM::VLD2d32wb_fixed, 4359 ARM::VLD1q64wb_fixed}; 4360 static const uint16_t QOpcodes[] = {ARM::VLD2q8PseudoWB_fixed, 4361 ARM::VLD2q16PseudoWB_fixed, 4362 ARM::VLD2q32PseudoWB_fixed}; 4363 SelectVLD(N, true, 2, DOpcodes, QOpcodes, nullptr); 4364 } else { 4365 static const uint16_t Opcodes8[] = {ARM::MVE_VLD20_8, 4366 ARM::MVE_VLD21_8_wb}; 4367 static const uint16_t Opcodes16[] = {ARM::MVE_VLD20_16, 4368 ARM::MVE_VLD21_16_wb}; 4369 static const uint16_t Opcodes32[] = {ARM::MVE_VLD20_32, 4370 ARM::MVE_VLD21_32_wb}; 4371 static const uint16_t *const Opcodes[] = {Opcodes8, Opcodes16, Opcodes32}; 4372 SelectMVE_VLD(N, 2, Opcodes, true); 4373 } 4374 return; 4375 } 4376 4377 case ARMISD::VLD3_UPD: { 4378 static const uint16_t DOpcodes[] = { ARM::VLD3d8Pseudo_UPD, 4379 ARM::VLD3d16Pseudo_UPD, 4380 ARM::VLD3d32Pseudo_UPD, 4381 ARM::VLD1d64TPseudoWB_fixed}; 4382 static const uint16_t QOpcodes0[] = { ARM::VLD3q8Pseudo_UPD, 4383 ARM::VLD3q16Pseudo_UPD, 4384 ARM::VLD3q32Pseudo_UPD }; 4385 static const uint16_t QOpcodes1[] = { ARM::VLD3q8oddPseudo_UPD, 4386 ARM::VLD3q16oddPseudo_UPD, 4387 ARM::VLD3q32oddPseudo_UPD }; 4388 SelectVLD(N, true, 3, DOpcodes, QOpcodes0, QOpcodes1); 4389 return; 4390 } 4391 4392 case ARMISD::VLD4_UPD: { 4393 if (Subtarget->hasNEON()) { 4394 static const uint16_t DOpcodes[] = { 4395 ARM::VLD4d8Pseudo_UPD, ARM::VLD4d16Pseudo_UPD, ARM::VLD4d32Pseudo_UPD, 4396 ARM::VLD1d64QPseudoWB_fixed}; 4397 static const uint16_t QOpcodes0[] = {ARM::VLD4q8Pseudo_UPD, 4398 ARM::VLD4q16Pseudo_UPD, 4399 ARM::VLD4q32Pseudo_UPD}; 4400 static const uint16_t QOpcodes1[] = {ARM::VLD4q8oddPseudo_UPD, 4401 ARM::VLD4q16oddPseudo_UPD, 4402 ARM::VLD4q32oddPseudo_UPD}; 4403 SelectVLD(N, true, 4, DOpcodes, QOpcodes0, QOpcodes1); 4404 } else { 4405 static const uint16_t Opcodes8[] = {ARM::MVE_VLD40_8, ARM::MVE_VLD41_8, 4406 ARM::MVE_VLD42_8, 4407 ARM::MVE_VLD43_8_wb}; 4408 static const uint16_t Opcodes16[] = {ARM::MVE_VLD40_16, ARM::MVE_VLD41_16, 4409 ARM::MVE_VLD42_16, 4410 ARM::MVE_VLD43_16_wb}; 4411 static const uint16_t Opcodes32[] = {ARM::MVE_VLD40_32, ARM::MVE_VLD41_32, 4412 ARM::MVE_VLD42_32, 4413 ARM::MVE_VLD43_32_wb}; 4414 static const uint16_t *const Opcodes[] = {Opcodes8, Opcodes16, Opcodes32}; 4415 SelectMVE_VLD(N, 4, Opcodes, true); 4416 } 4417 return; 4418 } 4419 4420 case ARMISD::VLD1x2_UPD: { 4421 if (Subtarget->hasNEON()) { 4422 static const uint16_t DOpcodes[] = { 4423 ARM::VLD1q8wb_fixed, ARM::VLD1q16wb_fixed, ARM::VLD1q32wb_fixed, 4424 ARM::VLD1q64wb_fixed}; 4425 static const uint16_t QOpcodes[] = { 4426 ARM::VLD1d8QPseudoWB_fixed, ARM::VLD1d16QPseudoWB_fixed, 4427 ARM::VLD1d32QPseudoWB_fixed, ARM::VLD1d64QPseudoWB_fixed}; 4428 SelectVLD(N, true, 2, DOpcodes, QOpcodes, nullptr); 4429 return; 4430 } 4431 break; 4432 } 4433 4434 case ARMISD::VLD1x3_UPD: { 4435 if (Subtarget->hasNEON()) { 4436 static const uint16_t DOpcodes[] = { 4437 ARM::VLD1d8TPseudoWB_fixed, ARM::VLD1d16TPseudoWB_fixed, 4438 ARM::VLD1d32TPseudoWB_fixed, ARM::VLD1d64TPseudoWB_fixed}; 4439 static const uint16_t QOpcodes0[] = { 4440 ARM::VLD1q8LowTPseudo_UPD, ARM::VLD1q16LowTPseudo_UPD, 4441 ARM::VLD1q32LowTPseudo_UPD, ARM::VLD1q64LowTPseudo_UPD}; 4442 static const uint16_t QOpcodes1[] = { 4443 ARM::VLD1q8HighTPseudo_UPD, ARM::VLD1q16HighTPseudo_UPD, 4444 ARM::VLD1q32HighTPseudo_UPD, ARM::VLD1q64HighTPseudo_UPD}; 4445 SelectVLD(N, true, 3, DOpcodes, QOpcodes0, QOpcodes1); 4446 return; 4447 } 4448 break; 4449 } 4450 4451 case ARMISD::VLD1x4_UPD: { 4452 if (Subtarget->hasNEON()) { 4453 static const uint16_t DOpcodes[] = { 4454 ARM::VLD1d8QPseudoWB_fixed, ARM::VLD1d16QPseudoWB_fixed, 4455 ARM::VLD1d32QPseudoWB_fixed, ARM::VLD1d64QPseudoWB_fixed}; 4456 static const uint16_t QOpcodes0[] = { 4457 ARM::VLD1q8LowQPseudo_UPD, ARM::VLD1q16LowQPseudo_UPD, 4458 ARM::VLD1q32LowQPseudo_UPD, ARM::VLD1q64LowQPseudo_UPD}; 4459 static const uint16_t QOpcodes1[] = { 4460 ARM::VLD1q8HighQPseudo_UPD, ARM::VLD1q16HighQPseudo_UPD, 4461 ARM::VLD1q32HighQPseudo_UPD, ARM::VLD1q64HighQPseudo_UPD}; 4462 SelectVLD(N, true, 4, DOpcodes, QOpcodes0, QOpcodes1); 4463 return; 4464 } 4465 break; 4466 } 4467 4468 case ARMISD::VLD2LN_UPD: { 4469 static const uint16_t DOpcodes[] = { ARM::VLD2LNd8Pseudo_UPD, 4470 ARM::VLD2LNd16Pseudo_UPD, 4471 ARM::VLD2LNd32Pseudo_UPD }; 4472 static const uint16_t QOpcodes[] = { ARM::VLD2LNq16Pseudo_UPD, 4473 ARM::VLD2LNq32Pseudo_UPD }; 4474 SelectVLDSTLane(N, true, true, 2, DOpcodes, QOpcodes); 4475 return; 4476 } 4477 4478 case ARMISD::VLD3LN_UPD: { 4479 static const uint16_t DOpcodes[] = { ARM::VLD3LNd8Pseudo_UPD, 4480 ARM::VLD3LNd16Pseudo_UPD, 4481 ARM::VLD3LNd32Pseudo_UPD }; 4482 static const uint16_t QOpcodes[] = { ARM::VLD3LNq16Pseudo_UPD, 4483 ARM::VLD3LNq32Pseudo_UPD }; 4484 SelectVLDSTLane(N, true, true, 3, DOpcodes, QOpcodes); 4485 return; 4486 } 4487 4488 case ARMISD::VLD4LN_UPD: { 4489 static const uint16_t DOpcodes[] = { ARM::VLD4LNd8Pseudo_UPD, 4490 ARM::VLD4LNd16Pseudo_UPD, 4491 ARM::VLD4LNd32Pseudo_UPD }; 4492 static const uint16_t QOpcodes[] = { ARM::VLD4LNq16Pseudo_UPD, 4493 ARM::VLD4LNq32Pseudo_UPD }; 4494 SelectVLDSTLane(N, true, true, 4, DOpcodes, QOpcodes); 4495 return; 4496 } 4497 4498 case ARMISD::VST1_UPD: { 4499 static const uint16_t DOpcodes[] = { ARM::VST1d8wb_fixed, 4500 ARM::VST1d16wb_fixed, 4501 ARM::VST1d32wb_fixed, 4502 ARM::VST1d64wb_fixed }; 4503 static const uint16_t QOpcodes[] = { ARM::VST1q8wb_fixed, 4504 ARM::VST1q16wb_fixed, 4505 ARM::VST1q32wb_fixed, 4506 ARM::VST1q64wb_fixed }; 4507 SelectVST(N, true, 1, DOpcodes, QOpcodes, nullptr); 4508 return; 4509 } 4510 4511 case ARMISD::VST2_UPD: { 4512 if (Subtarget->hasNEON()) { 4513 static const uint16_t DOpcodes[] = { 4514 ARM::VST2d8wb_fixed, ARM::VST2d16wb_fixed, ARM::VST2d32wb_fixed, 4515 ARM::VST1q64wb_fixed}; 4516 static const uint16_t QOpcodes[] = {ARM::VST2q8PseudoWB_fixed, 4517 ARM::VST2q16PseudoWB_fixed, 4518 ARM::VST2q32PseudoWB_fixed}; 4519 SelectVST(N, true, 2, DOpcodes, QOpcodes, nullptr); 4520 return; 4521 } 4522 break; 4523 } 4524 4525 case ARMISD::VST3_UPD: { 4526 static const uint16_t DOpcodes[] = { ARM::VST3d8Pseudo_UPD, 4527 ARM::VST3d16Pseudo_UPD, 4528 ARM::VST3d32Pseudo_UPD, 4529 ARM::VST1d64TPseudoWB_fixed}; 4530 static const uint16_t QOpcodes0[] = { ARM::VST3q8Pseudo_UPD, 4531 ARM::VST3q16Pseudo_UPD, 4532 ARM::VST3q32Pseudo_UPD }; 4533 static const uint16_t QOpcodes1[] = { ARM::VST3q8oddPseudo_UPD, 4534 ARM::VST3q16oddPseudo_UPD, 4535 ARM::VST3q32oddPseudo_UPD }; 4536 SelectVST(N, true, 3, DOpcodes, QOpcodes0, QOpcodes1); 4537 return; 4538 } 4539 4540 case ARMISD::VST4_UPD: { 4541 if (Subtarget->hasNEON()) { 4542 static const uint16_t DOpcodes[] = { 4543 ARM::VST4d8Pseudo_UPD, ARM::VST4d16Pseudo_UPD, ARM::VST4d32Pseudo_UPD, 4544 ARM::VST1d64QPseudoWB_fixed}; 4545 static const uint16_t QOpcodes0[] = {ARM::VST4q8Pseudo_UPD, 4546 ARM::VST4q16Pseudo_UPD, 4547 ARM::VST4q32Pseudo_UPD}; 4548 static const uint16_t QOpcodes1[] = {ARM::VST4q8oddPseudo_UPD, 4549 ARM::VST4q16oddPseudo_UPD, 4550 ARM::VST4q32oddPseudo_UPD}; 4551 SelectVST(N, true, 4, DOpcodes, QOpcodes0, QOpcodes1); 4552 return; 4553 } 4554 break; 4555 } 4556 4557 case ARMISD::VST1x2_UPD: { 4558 if (Subtarget->hasNEON()) { 4559 static const uint16_t DOpcodes[] = { ARM::VST1q8wb_fixed, 4560 ARM::VST1q16wb_fixed, 4561 ARM::VST1q32wb_fixed, 4562 ARM::VST1q64wb_fixed}; 4563 static const uint16_t QOpcodes[] = { ARM::VST1d8QPseudoWB_fixed, 4564 ARM::VST1d16QPseudoWB_fixed, 4565 ARM::VST1d32QPseudoWB_fixed, 4566 ARM::VST1d64QPseudoWB_fixed }; 4567 SelectVST(N, true, 2, DOpcodes, QOpcodes, nullptr); 4568 return; 4569 } 4570 break; 4571 } 4572 4573 case ARMISD::VST1x3_UPD: { 4574 if (Subtarget->hasNEON()) { 4575 static const uint16_t DOpcodes[] = { ARM::VST1d8TPseudoWB_fixed, 4576 ARM::VST1d16TPseudoWB_fixed, 4577 ARM::VST1d32TPseudoWB_fixed, 4578 ARM::VST1d64TPseudoWB_fixed }; 4579 static const uint16_t QOpcodes0[] = { ARM::VST1q8LowTPseudo_UPD, 4580 ARM::VST1q16LowTPseudo_UPD, 4581 ARM::VST1q32LowTPseudo_UPD, 4582 ARM::VST1q64LowTPseudo_UPD }; 4583 static const uint16_t QOpcodes1[] = { ARM::VST1q8HighTPseudo_UPD, 4584 ARM::VST1q16HighTPseudo_UPD, 4585 ARM::VST1q32HighTPseudo_UPD, 4586 ARM::VST1q64HighTPseudo_UPD }; 4587 SelectVST(N, true, 3, DOpcodes, QOpcodes0, QOpcodes1); 4588 return; 4589 } 4590 break; 4591 } 4592 4593 case ARMISD::VST1x4_UPD: { 4594 if (Subtarget->hasNEON()) { 4595 static const uint16_t DOpcodes[] = { ARM::VST1d8QPseudoWB_fixed, 4596 ARM::VST1d16QPseudoWB_fixed, 4597 ARM::VST1d32QPseudoWB_fixed, 4598 ARM::VST1d64QPseudoWB_fixed }; 4599 static const uint16_t QOpcodes0[] = { ARM::VST1q8LowQPseudo_UPD, 4600 ARM::VST1q16LowQPseudo_UPD, 4601 ARM::VST1q32LowQPseudo_UPD, 4602 ARM::VST1q64LowQPseudo_UPD }; 4603 static const uint16_t QOpcodes1[] = { ARM::VST1q8HighQPseudo_UPD, 4604 ARM::VST1q16HighQPseudo_UPD, 4605 ARM::VST1q32HighQPseudo_UPD, 4606 ARM::VST1q64HighQPseudo_UPD }; 4607 SelectVST(N, true, 4, DOpcodes, QOpcodes0, QOpcodes1); 4608 return; 4609 } 4610 break; 4611 } 4612 case ARMISD::VST2LN_UPD: { 4613 static const uint16_t DOpcodes[] = { ARM::VST2LNd8Pseudo_UPD, 4614 ARM::VST2LNd16Pseudo_UPD, 4615 ARM::VST2LNd32Pseudo_UPD }; 4616 static const uint16_t QOpcodes[] = { ARM::VST2LNq16Pseudo_UPD, 4617 ARM::VST2LNq32Pseudo_UPD }; 4618 SelectVLDSTLane(N, false, true, 2, DOpcodes, QOpcodes); 4619 return; 4620 } 4621 4622 case ARMISD::VST3LN_UPD: { 4623 static const uint16_t DOpcodes[] = { ARM::VST3LNd8Pseudo_UPD, 4624 ARM::VST3LNd16Pseudo_UPD, 4625 ARM::VST3LNd32Pseudo_UPD }; 4626 static const uint16_t QOpcodes[] = { ARM::VST3LNq16Pseudo_UPD, 4627 ARM::VST3LNq32Pseudo_UPD }; 4628 SelectVLDSTLane(N, false, true, 3, DOpcodes, QOpcodes); 4629 return; 4630 } 4631 4632 case ARMISD::VST4LN_UPD: { 4633 static const uint16_t DOpcodes[] = { ARM::VST4LNd8Pseudo_UPD, 4634 ARM::VST4LNd16Pseudo_UPD, 4635 ARM::VST4LNd32Pseudo_UPD }; 4636 static const uint16_t QOpcodes[] = { ARM::VST4LNq16Pseudo_UPD, 4637 ARM::VST4LNq32Pseudo_UPD }; 4638 SelectVLDSTLane(N, false, true, 4, DOpcodes, QOpcodes); 4639 return; 4640 } 4641 4642 case ISD::INTRINSIC_VOID: 4643 case ISD::INTRINSIC_W_CHAIN: { 4644 unsigned IntNo = cast<ConstantSDNode>(N->getOperand(1))->getZExtValue(); 4645 switch (IntNo) { 4646 default: 4647 break; 4648 4649 case Intrinsic::arm_mrrc: 4650 case Intrinsic::arm_mrrc2: { 4651 SDLoc dl(N); 4652 SDValue Chain = N->getOperand(0); 4653 unsigned Opc; 4654 4655 if (Subtarget->isThumb()) 4656 Opc = (IntNo == Intrinsic::arm_mrrc ? ARM::t2MRRC : ARM::t2MRRC2); 4657 else 4658 Opc = (IntNo == Intrinsic::arm_mrrc ? ARM::MRRC : ARM::MRRC2); 4659 4660 SmallVector<SDValue, 5> Ops; 4661 Ops.push_back(getI32Imm(cast<ConstantSDNode>(N->getOperand(2))->getZExtValue(), dl)); /* coproc */ 4662 Ops.push_back(getI32Imm(cast<ConstantSDNode>(N->getOperand(3))->getZExtValue(), dl)); /* opc */ 4663 Ops.push_back(getI32Imm(cast<ConstantSDNode>(N->getOperand(4))->getZExtValue(), dl)); /* CRm */ 4664 4665 // The mrrc2 instruction in ARM doesn't allow predicates, the top 4 bits of the encoded 4666 // instruction will always be '1111' but it is possible in assembly language to specify 4667 // AL as a predicate to mrrc2 but it doesn't make any difference to the encoded instruction. 4668 if (Opc != ARM::MRRC2) { 4669 Ops.push_back(getAL(CurDAG, dl)); 4670 Ops.push_back(CurDAG->getRegister(0, MVT::i32)); 4671 } 4672 4673 Ops.push_back(Chain); 4674 4675 // Writes to two registers. 4676 const EVT RetType[] = {MVT::i32, MVT::i32, MVT::Other}; 4677 4678 ReplaceNode(N, CurDAG->getMachineNode(Opc, dl, RetType, Ops)); 4679 return; 4680 } 4681 case Intrinsic::arm_ldaexd: 4682 case Intrinsic::arm_ldrexd: { 4683 SDLoc dl(N); 4684 SDValue Chain = N->getOperand(0); 4685 SDValue MemAddr = N->getOperand(2); 4686 bool isThumb = Subtarget->isThumb() && Subtarget->hasV8MBaselineOps(); 4687 4688 bool IsAcquire = IntNo == Intrinsic::arm_ldaexd; 4689 unsigned NewOpc = isThumb ? (IsAcquire ? ARM::t2LDAEXD : ARM::t2LDREXD) 4690 : (IsAcquire ? ARM::LDAEXD : ARM::LDREXD); 4691 4692 // arm_ldrexd returns a i64 value in {i32, i32} 4693 std::vector<EVT> ResTys; 4694 if (isThumb) { 4695 ResTys.push_back(MVT::i32); 4696 ResTys.push_back(MVT::i32); 4697 } else 4698 ResTys.push_back(MVT::Untyped); 4699 ResTys.push_back(MVT::Other); 4700 4701 // Place arguments in the right order. 4702 SDValue Ops[] = {MemAddr, getAL(CurDAG, dl), 4703 CurDAG->getRegister(0, MVT::i32), Chain}; 4704 SDNode *Ld = CurDAG->getMachineNode(NewOpc, dl, ResTys, Ops); 4705 // Transfer memoperands. 4706 MachineMemOperand *MemOp = cast<MemIntrinsicSDNode>(N)->getMemOperand(); 4707 CurDAG->setNodeMemRefs(cast<MachineSDNode>(Ld), {MemOp}); 4708 4709 // Remap uses. 4710 SDValue OutChain = isThumb ? SDValue(Ld, 2) : SDValue(Ld, 1); 4711 if (!SDValue(N, 0).use_empty()) { 4712 SDValue Result; 4713 if (isThumb) 4714 Result = SDValue(Ld, 0); 4715 else { 4716 SDValue SubRegIdx = 4717 CurDAG->getTargetConstant(ARM::gsub_0, dl, MVT::i32); 4718 SDNode *ResNode = CurDAG->getMachineNode(TargetOpcode::EXTRACT_SUBREG, 4719 dl, MVT::i32, SDValue(Ld, 0), SubRegIdx); 4720 Result = SDValue(ResNode,0); 4721 } 4722 ReplaceUses(SDValue(N, 0), Result); 4723 } 4724 if (!SDValue(N, 1).use_empty()) { 4725 SDValue Result; 4726 if (isThumb) 4727 Result = SDValue(Ld, 1); 4728 else { 4729 SDValue SubRegIdx = 4730 CurDAG->getTargetConstant(ARM::gsub_1, dl, MVT::i32); 4731 SDNode *ResNode = CurDAG->getMachineNode(TargetOpcode::EXTRACT_SUBREG, 4732 dl, MVT::i32, SDValue(Ld, 0), SubRegIdx); 4733 Result = SDValue(ResNode,0); 4734 } 4735 ReplaceUses(SDValue(N, 1), Result); 4736 } 4737 ReplaceUses(SDValue(N, 2), OutChain); 4738 CurDAG->RemoveDeadNode(N); 4739 return; 4740 } 4741 case Intrinsic::arm_stlexd: 4742 case Intrinsic::arm_strexd: { 4743 SDLoc dl(N); 4744 SDValue Chain = N->getOperand(0); 4745 SDValue Val0 = N->getOperand(2); 4746 SDValue Val1 = N->getOperand(3); 4747 SDValue MemAddr = N->getOperand(4); 4748 4749 // Store exclusive double return a i32 value which is the return status 4750 // of the issued store. 4751 const EVT ResTys[] = {MVT::i32, MVT::Other}; 4752 4753 bool isThumb = Subtarget->isThumb() && Subtarget->hasThumb2(); 4754 // Place arguments in the right order. 4755 SmallVector<SDValue, 7> Ops; 4756 if (isThumb) { 4757 Ops.push_back(Val0); 4758 Ops.push_back(Val1); 4759 } else 4760 // arm_strexd uses GPRPair. 4761 Ops.push_back(SDValue(createGPRPairNode(MVT::Untyped, Val0, Val1), 0)); 4762 Ops.push_back(MemAddr); 4763 Ops.push_back(getAL(CurDAG, dl)); 4764 Ops.push_back(CurDAG->getRegister(0, MVT::i32)); 4765 Ops.push_back(Chain); 4766 4767 bool IsRelease = IntNo == Intrinsic::arm_stlexd; 4768 unsigned NewOpc = isThumb ? (IsRelease ? ARM::t2STLEXD : ARM::t2STREXD) 4769 : (IsRelease ? ARM::STLEXD : ARM::STREXD); 4770 4771 SDNode *St = CurDAG->getMachineNode(NewOpc, dl, ResTys, Ops); 4772 // Transfer memoperands. 4773 MachineMemOperand *MemOp = cast<MemIntrinsicSDNode>(N)->getMemOperand(); 4774 CurDAG->setNodeMemRefs(cast<MachineSDNode>(St), {MemOp}); 4775 4776 ReplaceNode(N, St); 4777 return; 4778 } 4779 4780 case Intrinsic::arm_neon_vld1: { 4781 static const uint16_t DOpcodes[] = { ARM::VLD1d8, ARM::VLD1d16, 4782 ARM::VLD1d32, ARM::VLD1d64 }; 4783 static const uint16_t QOpcodes[] = { ARM::VLD1q8, ARM::VLD1q16, 4784 ARM::VLD1q32, ARM::VLD1q64}; 4785 SelectVLD(N, false, 1, DOpcodes, QOpcodes, nullptr); 4786 return; 4787 } 4788 4789 case Intrinsic::arm_neon_vld1x2: { 4790 static const uint16_t DOpcodes[] = { ARM::VLD1q8, ARM::VLD1q16, 4791 ARM::VLD1q32, ARM::VLD1q64 }; 4792 static const uint16_t QOpcodes[] = { ARM::VLD1d8QPseudo, 4793 ARM::VLD1d16QPseudo, 4794 ARM::VLD1d32QPseudo, 4795 ARM::VLD1d64QPseudo }; 4796 SelectVLD(N, false, 2, DOpcodes, QOpcodes, nullptr); 4797 return; 4798 } 4799 4800 case Intrinsic::arm_neon_vld1x3: { 4801 static const uint16_t DOpcodes[] = { ARM::VLD1d8TPseudo, 4802 ARM::VLD1d16TPseudo, 4803 ARM::VLD1d32TPseudo, 4804 ARM::VLD1d64TPseudo }; 4805 static const uint16_t QOpcodes0[] = { ARM::VLD1q8LowTPseudo_UPD, 4806 ARM::VLD1q16LowTPseudo_UPD, 4807 ARM::VLD1q32LowTPseudo_UPD, 4808 ARM::VLD1q64LowTPseudo_UPD }; 4809 static const uint16_t QOpcodes1[] = { ARM::VLD1q8HighTPseudo, 4810 ARM::VLD1q16HighTPseudo, 4811 ARM::VLD1q32HighTPseudo, 4812 ARM::VLD1q64HighTPseudo }; 4813 SelectVLD(N, false, 3, DOpcodes, QOpcodes0, QOpcodes1); 4814 return; 4815 } 4816 4817 case Intrinsic::arm_neon_vld1x4: { 4818 static const uint16_t DOpcodes[] = { ARM::VLD1d8QPseudo, 4819 ARM::VLD1d16QPseudo, 4820 ARM::VLD1d32QPseudo, 4821 ARM::VLD1d64QPseudo }; 4822 static const uint16_t QOpcodes0[] = { ARM::VLD1q8LowQPseudo_UPD, 4823 ARM::VLD1q16LowQPseudo_UPD, 4824 ARM::VLD1q32LowQPseudo_UPD, 4825 ARM::VLD1q64LowQPseudo_UPD }; 4826 static const uint16_t QOpcodes1[] = { ARM::VLD1q8HighQPseudo, 4827 ARM::VLD1q16HighQPseudo, 4828 ARM::VLD1q32HighQPseudo, 4829 ARM::VLD1q64HighQPseudo }; 4830 SelectVLD(N, false, 4, DOpcodes, QOpcodes0, QOpcodes1); 4831 return; 4832 } 4833 4834 case Intrinsic::arm_neon_vld2: { 4835 static const uint16_t DOpcodes[] = { ARM::VLD2d8, ARM::VLD2d16, 4836 ARM::VLD2d32, ARM::VLD1q64 }; 4837 static const uint16_t QOpcodes[] = { ARM::VLD2q8Pseudo, ARM::VLD2q16Pseudo, 4838 ARM::VLD2q32Pseudo }; 4839 SelectVLD(N, false, 2, DOpcodes, QOpcodes, nullptr); 4840 return; 4841 } 4842 4843 case Intrinsic::arm_neon_vld3: { 4844 static const uint16_t DOpcodes[] = { ARM::VLD3d8Pseudo, 4845 ARM::VLD3d16Pseudo, 4846 ARM::VLD3d32Pseudo, 4847 ARM::VLD1d64TPseudo }; 4848 static const uint16_t QOpcodes0[] = { ARM::VLD3q8Pseudo_UPD, 4849 ARM::VLD3q16Pseudo_UPD, 4850 ARM::VLD3q32Pseudo_UPD }; 4851 static const uint16_t QOpcodes1[] = { ARM::VLD3q8oddPseudo, 4852 ARM::VLD3q16oddPseudo, 4853 ARM::VLD3q32oddPseudo }; 4854 SelectVLD(N, false, 3, DOpcodes, QOpcodes0, QOpcodes1); 4855 return; 4856 } 4857 4858 case Intrinsic::arm_neon_vld4: { 4859 static const uint16_t DOpcodes[] = { ARM::VLD4d8Pseudo, 4860 ARM::VLD4d16Pseudo, 4861 ARM::VLD4d32Pseudo, 4862 ARM::VLD1d64QPseudo }; 4863 static const uint16_t QOpcodes0[] = { ARM::VLD4q8Pseudo_UPD, 4864 ARM::VLD4q16Pseudo_UPD, 4865 ARM::VLD4q32Pseudo_UPD }; 4866 static const uint16_t QOpcodes1[] = { ARM::VLD4q8oddPseudo, 4867 ARM::VLD4q16oddPseudo, 4868 ARM::VLD4q32oddPseudo }; 4869 SelectVLD(N, false, 4, DOpcodes, QOpcodes0, QOpcodes1); 4870 return; 4871 } 4872 4873 case Intrinsic::arm_neon_vld2dup: { 4874 static const uint16_t DOpcodes[] = { ARM::VLD2DUPd8, ARM::VLD2DUPd16, 4875 ARM::VLD2DUPd32, ARM::VLD1q64 }; 4876 static const uint16_t QOpcodes0[] = { ARM::VLD2DUPq8EvenPseudo, 4877 ARM::VLD2DUPq16EvenPseudo, 4878 ARM::VLD2DUPq32EvenPseudo }; 4879 static const uint16_t QOpcodes1[] = { ARM::VLD2DUPq8OddPseudo, 4880 ARM::VLD2DUPq16OddPseudo, 4881 ARM::VLD2DUPq32OddPseudo }; 4882 SelectVLDDup(N, /* IsIntrinsic= */ true, false, 2, 4883 DOpcodes, QOpcodes0, QOpcodes1); 4884 return; 4885 } 4886 4887 case Intrinsic::arm_neon_vld3dup: { 4888 static const uint16_t DOpcodes[] = { ARM::VLD3DUPd8Pseudo, 4889 ARM::VLD3DUPd16Pseudo, 4890 ARM::VLD3DUPd32Pseudo, 4891 ARM::VLD1d64TPseudo }; 4892 static const uint16_t QOpcodes0[] = { ARM::VLD3DUPq8EvenPseudo, 4893 ARM::VLD3DUPq16EvenPseudo, 4894 ARM::VLD3DUPq32EvenPseudo }; 4895 static const uint16_t QOpcodes1[] = { ARM::VLD3DUPq8OddPseudo, 4896 ARM::VLD3DUPq16OddPseudo, 4897 ARM::VLD3DUPq32OddPseudo }; 4898 SelectVLDDup(N, /* IsIntrinsic= */ true, false, 3, 4899 DOpcodes, QOpcodes0, QOpcodes1); 4900 return; 4901 } 4902 4903 case Intrinsic::arm_neon_vld4dup: { 4904 static const uint16_t DOpcodes[] = { ARM::VLD4DUPd8Pseudo, 4905 ARM::VLD4DUPd16Pseudo, 4906 ARM::VLD4DUPd32Pseudo, 4907 ARM::VLD1d64QPseudo }; 4908 static const uint16_t QOpcodes0[] = { ARM::VLD4DUPq8EvenPseudo, 4909 ARM::VLD4DUPq16EvenPseudo, 4910 ARM::VLD4DUPq32EvenPseudo }; 4911 static const uint16_t QOpcodes1[] = { ARM::VLD4DUPq8OddPseudo, 4912 ARM::VLD4DUPq16OddPseudo, 4913 ARM::VLD4DUPq32OddPseudo }; 4914 SelectVLDDup(N, /* IsIntrinsic= */ true, false, 4, 4915 DOpcodes, QOpcodes0, QOpcodes1); 4916 return; 4917 } 4918 4919 case Intrinsic::arm_neon_vld2lane: { 4920 static const uint16_t DOpcodes[] = { ARM::VLD2LNd8Pseudo, 4921 ARM::VLD2LNd16Pseudo, 4922 ARM::VLD2LNd32Pseudo }; 4923 static const uint16_t QOpcodes[] = { ARM::VLD2LNq16Pseudo, 4924 ARM::VLD2LNq32Pseudo }; 4925 SelectVLDSTLane(N, true, false, 2, DOpcodes, QOpcodes); 4926 return; 4927 } 4928 4929 case Intrinsic::arm_neon_vld3lane: { 4930 static const uint16_t DOpcodes[] = { ARM::VLD3LNd8Pseudo, 4931 ARM::VLD3LNd16Pseudo, 4932 ARM::VLD3LNd32Pseudo }; 4933 static const uint16_t QOpcodes[] = { ARM::VLD3LNq16Pseudo, 4934 ARM::VLD3LNq32Pseudo }; 4935 SelectVLDSTLane(N, true, false, 3, DOpcodes, QOpcodes); 4936 return; 4937 } 4938 4939 case Intrinsic::arm_neon_vld4lane: { 4940 static const uint16_t DOpcodes[] = { ARM::VLD4LNd8Pseudo, 4941 ARM::VLD4LNd16Pseudo, 4942 ARM::VLD4LNd32Pseudo }; 4943 static const uint16_t QOpcodes[] = { ARM::VLD4LNq16Pseudo, 4944 ARM::VLD4LNq32Pseudo }; 4945 SelectVLDSTLane(N, true, false, 4, DOpcodes, QOpcodes); 4946 return; 4947 } 4948 4949 case Intrinsic::arm_neon_vst1: { 4950 static const uint16_t DOpcodes[] = { ARM::VST1d8, ARM::VST1d16, 4951 ARM::VST1d32, ARM::VST1d64 }; 4952 static const uint16_t QOpcodes[] = { ARM::VST1q8, ARM::VST1q16, 4953 ARM::VST1q32, ARM::VST1q64 }; 4954 SelectVST(N, false, 1, DOpcodes, QOpcodes, nullptr); 4955 return; 4956 } 4957 4958 case Intrinsic::arm_neon_vst1x2: { 4959 static const uint16_t DOpcodes[] = { ARM::VST1q8, ARM::VST1q16, 4960 ARM::VST1q32, ARM::VST1q64 }; 4961 static const uint16_t QOpcodes[] = { ARM::VST1d8QPseudo, 4962 ARM::VST1d16QPseudo, 4963 ARM::VST1d32QPseudo, 4964 ARM::VST1d64QPseudo }; 4965 SelectVST(N, false, 2, DOpcodes, QOpcodes, nullptr); 4966 return; 4967 } 4968 4969 case Intrinsic::arm_neon_vst1x3: { 4970 static const uint16_t DOpcodes[] = { ARM::VST1d8TPseudo, 4971 ARM::VST1d16TPseudo, 4972 ARM::VST1d32TPseudo, 4973 ARM::VST1d64TPseudo }; 4974 static const uint16_t QOpcodes0[] = { ARM::VST1q8LowTPseudo_UPD, 4975 ARM::VST1q16LowTPseudo_UPD, 4976 ARM::VST1q32LowTPseudo_UPD, 4977 ARM::VST1q64LowTPseudo_UPD }; 4978 static const uint16_t QOpcodes1[] = { ARM::VST1q8HighTPseudo, 4979 ARM::VST1q16HighTPseudo, 4980 ARM::VST1q32HighTPseudo, 4981 ARM::VST1q64HighTPseudo }; 4982 SelectVST(N, false, 3, DOpcodes, QOpcodes0, QOpcodes1); 4983 return; 4984 } 4985 4986 case Intrinsic::arm_neon_vst1x4: { 4987 static const uint16_t DOpcodes[] = { ARM::VST1d8QPseudo, 4988 ARM::VST1d16QPseudo, 4989 ARM::VST1d32QPseudo, 4990 ARM::VST1d64QPseudo }; 4991 static const uint16_t QOpcodes0[] = { ARM::VST1q8LowQPseudo_UPD, 4992 ARM::VST1q16LowQPseudo_UPD, 4993 ARM::VST1q32LowQPseudo_UPD, 4994 ARM::VST1q64LowQPseudo_UPD }; 4995 static const uint16_t QOpcodes1[] = { ARM::VST1q8HighQPseudo, 4996 ARM::VST1q16HighQPseudo, 4997 ARM::VST1q32HighQPseudo, 4998 ARM::VST1q64HighQPseudo }; 4999 SelectVST(N, false, 4, DOpcodes, QOpcodes0, QOpcodes1); 5000 return; 5001 } 5002 5003 case Intrinsic::arm_neon_vst2: { 5004 static const uint16_t DOpcodes[] = { ARM::VST2d8, ARM::VST2d16, 5005 ARM::VST2d32, ARM::VST1q64 }; 5006 static const uint16_t QOpcodes[] = { ARM::VST2q8Pseudo, ARM::VST2q16Pseudo, 5007 ARM::VST2q32Pseudo }; 5008 SelectVST(N, false, 2, DOpcodes, QOpcodes, nullptr); 5009 return; 5010 } 5011 5012 case Intrinsic::arm_neon_vst3: { 5013 static const uint16_t DOpcodes[] = { ARM::VST3d8Pseudo, 5014 ARM::VST3d16Pseudo, 5015 ARM::VST3d32Pseudo, 5016 ARM::VST1d64TPseudo }; 5017 static const uint16_t QOpcodes0[] = { ARM::VST3q8Pseudo_UPD, 5018 ARM::VST3q16Pseudo_UPD, 5019 ARM::VST3q32Pseudo_UPD }; 5020 static const uint16_t QOpcodes1[] = { ARM::VST3q8oddPseudo, 5021 ARM::VST3q16oddPseudo, 5022 ARM::VST3q32oddPseudo }; 5023 SelectVST(N, false, 3, DOpcodes, QOpcodes0, QOpcodes1); 5024 return; 5025 } 5026 5027 case Intrinsic::arm_neon_vst4: { 5028 static const uint16_t DOpcodes[] = { ARM::VST4d8Pseudo, 5029 ARM::VST4d16Pseudo, 5030 ARM::VST4d32Pseudo, 5031 ARM::VST1d64QPseudo }; 5032 static const uint16_t QOpcodes0[] = { ARM::VST4q8Pseudo_UPD, 5033 ARM::VST4q16Pseudo_UPD, 5034 ARM::VST4q32Pseudo_UPD }; 5035 static const uint16_t QOpcodes1[] = { ARM::VST4q8oddPseudo, 5036 ARM::VST4q16oddPseudo, 5037 ARM::VST4q32oddPseudo }; 5038 SelectVST(N, false, 4, DOpcodes, QOpcodes0, QOpcodes1); 5039 return; 5040 } 5041 5042 case Intrinsic::arm_neon_vst2lane: { 5043 static const uint16_t DOpcodes[] = { ARM::VST2LNd8Pseudo, 5044 ARM::VST2LNd16Pseudo, 5045 ARM::VST2LNd32Pseudo }; 5046 static const uint16_t QOpcodes[] = { ARM::VST2LNq16Pseudo, 5047 ARM::VST2LNq32Pseudo }; 5048 SelectVLDSTLane(N, false, false, 2, DOpcodes, QOpcodes); 5049 return; 5050 } 5051 5052 case Intrinsic::arm_neon_vst3lane: { 5053 static const uint16_t DOpcodes[] = { ARM::VST3LNd8Pseudo, 5054 ARM::VST3LNd16Pseudo, 5055 ARM::VST3LNd32Pseudo }; 5056 static const uint16_t QOpcodes[] = { ARM::VST3LNq16Pseudo, 5057 ARM::VST3LNq32Pseudo }; 5058 SelectVLDSTLane(N, false, false, 3, DOpcodes, QOpcodes); 5059 return; 5060 } 5061 5062 case Intrinsic::arm_neon_vst4lane: { 5063 static const uint16_t DOpcodes[] = { ARM::VST4LNd8Pseudo, 5064 ARM::VST4LNd16Pseudo, 5065 ARM::VST4LNd32Pseudo }; 5066 static const uint16_t QOpcodes[] = { ARM::VST4LNq16Pseudo, 5067 ARM::VST4LNq32Pseudo }; 5068 SelectVLDSTLane(N, false, false, 4, DOpcodes, QOpcodes); 5069 return; 5070 } 5071 5072 case Intrinsic::arm_mve_vldr_gather_base_wb: 5073 case Intrinsic::arm_mve_vldr_gather_base_wb_predicated: { 5074 static const uint16_t Opcodes[] = {ARM::MVE_VLDRWU32_qi_pre, 5075 ARM::MVE_VLDRDU64_qi_pre}; 5076 SelectMVE_WB(N, Opcodes, 5077 IntNo == Intrinsic::arm_mve_vldr_gather_base_wb_predicated); 5078 return; 5079 } 5080 5081 case Intrinsic::arm_mve_vld2q: { 5082 static const uint16_t Opcodes8[] = {ARM::MVE_VLD20_8, ARM::MVE_VLD21_8}; 5083 static const uint16_t Opcodes16[] = {ARM::MVE_VLD20_16, 5084 ARM::MVE_VLD21_16}; 5085 static const uint16_t Opcodes32[] = {ARM::MVE_VLD20_32, 5086 ARM::MVE_VLD21_32}; 5087 static const uint16_t *const Opcodes[] = {Opcodes8, Opcodes16, Opcodes32}; 5088 SelectMVE_VLD(N, 2, Opcodes, false); 5089 return; 5090 } 5091 5092 case Intrinsic::arm_mve_vld4q: { 5093 static const uint16_t Opcodes8[] = {ARM::MVE_VLD40_8, ARM::MVE_VLD41_8, 5094 ARM::MVE_VLD42_8, ARM::MVE_VLD43_8}; 5095 static const uint16_t Opcodes16[] = {ARM::MVE_VLD40_16, ARM::MVE_VLD41_16, 5096 ARM::MVE_VLD42_16, 5097 ARM::MVE_VLD43_16}; 5098 static const uint16_t Opcodes32[] = {ARM::MVE_VLD40_32, ARM::MVE_VLD41_32, 5099 ARM::MVE_VLD42_32, 5100 ARM::MVE_VLD43_32}; 5101 static const uint16_t *const Opcodes[] = {Opcodes8, Opcodes16, Opcodes32}; 5102 SelectMVE_VLD(N, 4, Opcodes, false); 5103 return; 5104 } 5105 } 5106 break; 5107 } 5108 5109 case ISD::INTRINSIC_WO_CHAIN: { 5110 unsigned IntNo = cast<ConstantSDNode>(N->getOperand(0))->getZExtValue(); 5111 switch (IntNo) { 5112 default: 5113 break; 5114 5115 // Scalar f32 -> bf16 5116 case Intrinsic::arm_neon_vcvtbfp2bf: { 5117 SDLoc dl(N); 5118 const SDValue &Src = N->getOperand(1); 5119 llvm::EVT DestTy = N->getValueType(0); 5120 SDValue Pred = getAL(CurDAG, dl); 5121 SDValue Reg0 = CurDAG->getRegister(0, MVT::i32); 5122 SDValue Ops[] = { Src, Src, Pred, Reg0 }; 5123 CurDAG->SelectNodeTo(N, ARM::BF16_VCVTB, DestTy, Ops); 5124 return; 5125 } 5126 5127 // Vector v4f32 -> v4bf16 5128 case Intrinsic::arm_neon_vcvtfp2bf: { 5129 SDLoc dl(N); 5130 const SDValue &Src = N->getOperand(1); 5131 SDValue Pred = getAL(CurDAG, dl); 5132 SDValue Reg0 = CurDAG->getRegister(0, MVT::i32); 5133 SDValue Ops[] = { Src, Pred, Reg0 }; 5134 CurDAG->SelectNodeTo(N, ARM::BF16_VCVT, MVT::v4bf16, Ops); 5135 return; 5136 } 5137 5138 case Intrinsic::arm_mve_urshrl: 5139 SelectMVE_LongShift(N, ARM::MVE_URSHRL, true, false); 5140 return; 5141 case Intrinsic::arm_mve_uqshll: 5142 SelectMVE_LongShift(N, ARM::MVE_UQSHLL, true, false); 5143 return; 5144 case Intrinsic::arm_mve_srshrl: 5145 SelectMVE_LongShift(N, ARM::MVE_SRSHRL, true, false); 5146 return; 5147 case Intrinsic::arm_mve_sqshll: 5148 SelectMVE_LongShift(N, ARM::MVE_SQSHLL, true, false); 5149 return; 5150 case Intrinsic::arm_mve_uqrshll: 5151 SelectMVE_LongShift(N, ARM::MVE_UQRSHLL, false, true); 5152 return; 5153 case Intrinsic::arm_mve_sqrshrl: 5154 SelectMVE_LongShift(N, ARM::MVE_SQRSHRL, false, true); 5155 return; 5156 5157 case Intrinsic::arm_mve_vadc: 5158 case Intrinsic::arm_mve_vadc_predicated: 5159 SelectMVE_VADCSBC(N, ARM::MVE_VADC, ARM::MVE_VADCI, true, 5160 IntNo == Intrinsic::arm_mve_vadc_predicated); 5161 return; 5162 case Intrinsic::arm_mve_vsbc: 5163 case Intrinsic::arm_mve_vsbc_predicated: 5164 SelectMVE_VADCSBC(N, ARM::MVE_VSBC, ARM::MVE_VSBCI, true, 5165 IntNo == Intrinsic::arm_mve_vsbc_predicated); 5166 return; 5167 case Intrinsic::arm_mve_vshlc: 5168 case Intrinsic::arm_mve_vshlc_predicated: 5169 SelectMVE_VSHLC(N, IntNo == Intrinsic::arm_mve_vshlc_predicated); 5170 return; 5171 5172 case Intrinsic::arm_mve_vmlldava: 5173 case Intrinsic::arm_mve_vmlldava_predicated: { 5174 static const uint16_t OpcodesU[] = { 5175 ARM::MVE_VMLALDAVu16, ARM::MVE_VMLALDAVu32, 5176 ARM::MVE_VMLALDAVau16, ARM::MVE_VMLALDAVau32, 5177 }; 5178 static const uint16_t OpcodesS[] = { 5179 ARM::MVE_VMLALDAVs16, ARM::MVE_VMLALDAVs32, 5180 ARM::MVE_VMLALDAVas16, ARM::MVE_VMLALDAVas32, 5181 ARM::MVE_VMLALDAVxs16, ARM::MVE_VMLALDAVxs32, 5182 ARM::MVE_VMLALDAVaxs16, ARM::MVE_VMLALDAVaxs32, 5183 ARM::MVE_VMLSLDAVs16, ARM::MVE_VMLSLDAVs32, 5184 ARM::MVE_VMLSLDAVas16, ARM::MVE_VMLSLDAVas32, 5185 ARM::MVE_VMLSLDAVxs16, ARM::MVE_VMLSLDAVxs32, 5186 ARM::MVE_VMLSLDAVaxs16, ARM::MVE_VMLSLDAVaxs32, 5187 }; 5188 SelectMVE_VMLLDAV(N, IntNo == Intrinsic::arm_mve_vmlldava_predicated, 5189 OpcodesS, OpcodesU); 5190 return; 5191 } 5192 5193 case Intrinsic::arm_mve_vrmlldavha: 5194 case Intrinsic::arm_mve_vrmlldavha_predicated: { 5195 static const uint16_t OpcodesU[] = { 5196 ARM::MVE_VRMLALDAVHu32, ARM::MVE_VRMLALDAVHau32, 5197 }; 5198 static const uint16_t OpcodesS[] = { 5199 ARM::MVE_VRMLALDAVHs32, ARM::MVE_VRMLALDAVHas32, 5200 ARM::MVE_VRMLALDAVHxs32, ARM::MVE_VRMLALDAVHaxs32, 5201 ARM::MVE_VRMLSLDAVHs32, ARM::MVE_VRMLSLDAVHas32, 5202 ARM::MVE_VRMLSLDAVHxs32, ARM::MVE_VRMLSLDAVHaxs32, 5203 }; 5204 SelectMVE_VRMLLDAVH(N, IntNo == Intrinsic::arm_mve_vrmlldavha_predicated, 5205 OpcodesS, OpcodesU); 5206 return; 5207 } 5208 5209 case Intrinsic::arm_mve_vidup: 5210 case Intrinsic::arm_mve_vidup_predicated: { 5211 static const uint16_t Opcodes[] = { 5212 ARM::MVE_VIDUPu8, ARM::MVE_VIDUPu16, ARM::MVE_VIDUPu32, 5213 }; 5214 SelectMVE_VxDUP(N, Opcodes, false, 5215 IntNo == Intrinsic::arm_mve_vidup_predicated); 5216 return; 5217 } 5218 5219 case Intrinsic::arm_mve_vddup: 5220 case Intrinsic::arm_mve_vddup_predicated: { 5221 static const uint16_t Opcodes[] = { 5222 ARM::MVE_VDDUPu8, ARM::MVE_VDDUPu16, ARM::MVE_VDDUPu32, 5223 }; 5224 SelectMVE_VxDUP(N, Opcodes, false, 5225 IntNo == Intrinsic::arm_mve_vddup_predicated); 5226 return; 5227 } 5228 5229 case Intrinsic::arm_mve_viwdup: 5230 case Intrinsic::arm_mve_viwdup_predicated: { 5231 static const uint16_t Opcodes[] = { 5232 ARM::MVE_VIWDUPu8, ARM::MVE_VIWDUPu16, ARM::MVE_VIWDUPu32, 5233 }; 5234 SelectMVE_VxDUP(N, Opcodes, true, 5235 IntNo == Intrinsic::arm_mve_viwdup_predicated); 5236 return; 5237 } 5238 5239 case Intrinsic::arm_mve_vdwdup: 5240 case Intrinsic::arm_mve_vdwdup_predicated: { 5241 static const uint16_t Opcodes[] = { 5242 ARM::MVE_VDWDUPu8, ARM::MVE_VDWDUPu16, ARM::MVE_VDWDUPu32, 5243 }; 5244 SelectMVE_VxDUP(N, Opcodes, true, 5245 IntNo == Intrinsic::arm_mve_vdwdup_predicated); 5246 return; 5247 } 5248 5249 case Intrinsic::arm_cde_cx1d: 5250 case Intrinsic::arm_cde_cx1da: 5251 case Intrinsic::arm_cde_cx2d: 5252 case Intrinsic::arm_cde_cx2da: 5253 case Intrinsic::arm_cde_cx3d: 5254 case Intrinsic::arm_cde_cx3da: { 5255 bool HasAccum = IntNo == Intrinsic::arm_cde_cx1da || 5256 IntNo == Intrinsic::arm_cde_cx2da || 5257 IntNo == Intrinsic::arm_cde_cx3da; 5258 size_t NumExtraOps; 5259 uint16_t Opcode; 5260 switch (IntNo) { 5261 case Intrinsic::arm_cde_cx1d: 5262 case Intrinsic::arm_cde_cx1da: 5263 NumExtraOps = 0; 5264 Opcode = HasAccum ? ARM::CDE_CX1DA : ARM::CDE_CX1D; 5265 break; 5266 case Intrinsic::arm_cde_cx2d: 5267 case Intrinsic::arm_cde_cx2da: 5268 NumExtraOps = 1; 5269 Opcode = HasAccum ? ARM::CDE_CX2DA : ARM::CDE_CX2D; 5270 break; 5271 case Intrinsic::arm_cde_cx3d: 5272 case Intrinsic::arm_cde_cx3da: 5273 NumExtraOps = 2; 5274 Opcode = HasAccum ? ARM::CDE_CX3DA : ARM::CDE_CX3D; 5275 break; 5276 default: 5277 llvm_unreachable("Unexpected opcode"); 5278 } 5279 SelectCDE_CXxD(N, Opcode, NumExtraOps, HasAccum); 5280 return; 5281 } 5282 } 5283 break; 5284 } 5285 5286 case ISD::ATOMIC_CMP_SWAP: 5287 SelectCMP_SWAP(N); 5288 return; 5289 } 5290 5291 SelectCode(N); 5292 } 5293 5294 // Inspect a register string of the form 5295 // cp<coprocessor>:<opc1>:c<CRn>:c<CRm>:<opc2> (32bit) or 5296 // cp<coprocessor>:<opc1>:c<CRm> (64bit) inspect the fields of the string 5297 // and obtain the integer operands from them, adding these operands to the 5298 // provided vector. 5299 static void getIntOperandsFromRegisterString(StringRef RegString, 5300 SelectionDAG *CurDAG, 5301 const SDLoc &DL, 5302 std::vector<SDValue> &Ops) { 5303 SmallVector<StringRef, 5> Fields; 5304 RegString.split(Fields, ':'); 5305 5306 if (Fields.size() > 1) { 5307 bool AllIntFields = true; 5308 5309 for (StringRef Field : Fields) { 5310 // Need to trim out leading 'cp' characters and get the integer field. 5311 unsigned IntField; 5312 AllIntFields &= !Field.trim("CPcp").getAsInteger(10, IntField); 5313 Ops.push_back(CurDAG->getTargetConstant(IntField, DL, MVT::i32)); 5314 } 5315 5316 assert(AllIntFields && 5317 "Unexpected non-integer value in special register string."); 5318 (void)AllIntFields; 5319 } 5320 } 5321 5322 // Maps a Banked Register string to its mask value. The mask value returned is 5323 // for use in the MRSbanked / MSRbanked instruction nodes as the Banked Register 5324 // mask operand, which expresses which register is to be used, e.g. r8, and in 5325 // which mode it is to be used, e.g. usr. Returns -1 to signify that the string 5326 // was invalid. 5327 static inline int getBankedRegisterMask(StringRef RegString) { 5328 auto TheReg = ARMBankedReg::lookupBankedRegByName(RegString.lower()); 5329 if (!TheReg) 5330 return -1; 5331 return TheReg->Encoding; 5332 } 5333 5334 // The flags here are common to those allowed for apsr in the A class cores and 5335 // those allowed for the special registers in the M class cores. Returns a 5336 // value representing which flags were present, -1 if invalid. 5337 static inline int getMClassFlagsMask(StringRef Flags) { 5338 return StringSwitch<int>(Flags) 5339 .Case("", 0x2) // no flags means nzcvq for psr registers, and 0x2 is 5340 // correct when flags are not permitted 5341 .Case("g", 0x1) 5342 .Case("nzcvq", 0x2) 5343 .Case("nzcvqg", 0x3) 5344 .Default(-1); 5345 } 5346 5347 // Maps MClass special registers string to its value for use in the 5348 // t2MRS_M/t2MSR_M instruction nodes as the SYSm value operand. 5349 // Returns -1 to signify that the string was invalid. 5350 static int getMClassRegisterMask(StringRef Reg, const ARMSubtarget *Subtarget) { 5351 auto TheReg = ARMSysReg::lookupMClassSysRegByName(Reg); 5352 const FeatureBitset &FeatureBits = Subtarget->getFeatureBits(); 5353 if (!TheReg || !TheReg->hasRequiredFeatures(FeatureBits)) 5354 return -1; 5355 return (int)(TheReg->Encoding & 0xFFF); // SYSm value 5356 } 5357 5358 static int getARClassRegisterMask(StringRef Reg, StringRef Flags) { 5359 // The mask operand contains the special register (R Bit) in bit 4, whether 5360 // the register is spsr (R bit is 1) or one of cpsr/apsr (R bit is 0), and 5361 // bits 3-0 contains the fields to be accessed in the special register, set by 5362 // the flags provided with the register. 5363 int Mask = 0; 5364 if (Reg == "apsr") { 5365 // The flags permitted for apsr are the same flags that are allowed in 5366 // M class registers. We get the flag value and then shift the flags into 5367 // the correct place to combine with the mask. 5368 Mask = getMClassFlagsMask(Flags); 5369 if (Mask == -1) 5370 return -1; 5371 return Mask << 2; 5372 } 5373 5374 if (Reg != "cpsr" && Reg != "spsr") { 5375 return -1; 5376 } 5377 5378 // This is the same as if the flags were "fc" 5379 if (Flags.empty() || Flags == "all") 5380 return Mask | 0x9; 5381 5382 // Inspect the supplied flags string and set the bits in the mask for 5383 // the relevant and valid flags allowed for cpsr and spsr. 5384 for (char Flag : Flags) { 5385 int FlagVal; 5386 switch (Flag) { 5387 case 'c': 5388 FlagVal = 0x1; 5389 break; 5390 case 'x': 5391 FlagVal = 0x2; 5392 break; 5393 case 's': 5394 FlagVal = 0x4; 5395 break; 5396 case 'f': 5397 FlagVal = 0x8; 5398 break; 5399 default: 5400 FlagVal = 0; 5401 } 5402 5403 // This avoids allowing strings where the same flag bit appears twice. 5404 if (!FlagVal || (Mask & FlagVal)) 5405 return -1; 5406 Mask |= FlagVal; 5407 } 5408 5409 // If the register is spsr then we need to set the R bit. 5410 if (Reg == "spsr") 5411 Mask |= 0x10; 5412 5413 return Mask; 5414 } 5415 5416 // Lower the read_register intrinsic to ARM specific DAG nodes 5417 // using the supplied metadata string to select the instruction node to use 5418 // and the registers/masks to construct as operands for the node. 5419 bool ARMDAGToDAGISel::tryReadRegister(SDNode *N){ 5420 const MDNodeSDNode *MD = dyn_cast<MDNodeSDNode>(N->getOperand(1)); 5421 const MDString *RegString = dyn_cast<MDString>(MD->getMD()->getOperand(0)); 5422 bool IsThumb2 = Subtarget->isThumb2(); 5423 SDLoc DL(N); 5424 5425 std::vector<SDValue> Ops; 5426 getIntOperandsFromRegisterString(RegString->getString(), CurDAG, DL, Ops); 5427 5428 if (!Ops.empty()) { 5429 // If the special register string was constructed of fields (as defined 5430 // in the ACLE) then need to lower to MRC node (32 bit) or 5431 // MRRC node(64 bit), we can make the distinction based on the number of 5432 // operands we have. 5433 unsigned Opcode; 5434 SmallVector<EVT, 3> ResTypes; 5435 if (Ops.size() == 5){ 5436 Opcode = IsThumb2 ? ARM::t2MRC : ARM::MRC; 5437 ResTypes.append({ MVT::i32, MVT::Other }); 5438 } else { 5439 assert(Ops.size() == 3 && 5440 "Invalid number of fields in special register string."); 5441 Opcode = IsThumb2 ? ARM::t2MRRC : ARM::MRRC; 5442 ResTypes.append({ MVT::i32, MVT::i32, MVT::Other }); 5443 } 5444 5445 Ops.push_back(getAL(CurDAG, DL)); 5446 Ops.push_back(CurDAG->getRegister(0, MVT::i32)); 5447 Ops.push_back(N->getOperand(0)); 5448 ReplaceNode(N, CurDAG->getMachineNode(Opcode, DL, ResTypes, Ops)); 5449 return true; 5450 } 5451 5452 std::string SpecialReg = RegString->getString().lower(); 5453 5454 int BankedReg = getBankedRegisterMask(SpecialReg); 5455 if (BankedReg != -1) { 5456 Ops = { CurDAG->getTargetConstant(BankedReg, DL, MVT::i32), 5457 getAL(CurDAG, DL), CurDAG->getRegister(0, MVT::i32), 5458 N->getOperand(0) }; 5459 ReplaceNode( 5460 N, CurDAG->getMachineNode(IsThumb2 ? ARM::t2MRSbanked : ARM::MRSbanked, 5461 DL, MVT::i32, MVT::Other, Ops)); 5462 return true; 5463 } 5464 5465 // The VFP registers are read by creating SelectionDAG nodes with opcodes 5466 // corresponding to the register that is being read from. So we switch on the 5467 // string to find which opcode we need to use. 5468 unsigned Opcode = StringSwitch<unsigned>(SpecialReg) 5469 .Case("fpscr", ARM::VMRS) 5470 .Case("fpexc", ARM::VMRS_FPEXC) 5471 .Case("fpsid", ARM::VMRS_FPSID) 5472 .Case("mvfr0", ARM::VMRS_MVFR0) 5473 .Case("mvfr1", ARM::VMRS_MVFR1) 5474 .Case("mvfr2", ARM::VMRS_MVFR2) 5475 .Case("fpinst", ARM::VMRS_FPINST) 5476 .Case("fpinst2", ARM::VMRS_FPINST2) 5477 .Default(0); 5478 5479 // If an opcode was found then we can lower the read to a VFP instruction. 5480 if (Opcode) { 5481 if (!Subtarget->hasVFP2Base()) 5482 return false; 5483 if (Opcode == ARM::VMRS_MVFR2 && !Subtarget->hasFPARMv8Base()) 5484 return false; 5485 5486 Ops = { getAL(CurDAG, DL), CurDAG->getRegister(0, MVT::i32), 5487 N->getOperand(0) }; 5488 ReplaceNode(N, 5489 CurDAG->getMachineNode(Opcode, DL, MVT::i32, MVT::Other, Ops)); 5490 return true; 5491 } 5492 5493 // If the target is M Class then need to validate that the register string 5494 // is an acceptable value, so check that a mask can be constructed from the 5495 // string. 5496 if (Subtarget->isMClass()) { 5497 int SYSmValue = getMClassRegisterMask(SpecialReg, Subtarget); 5498 if (SYSmValue == -1) 5499 return false; 5500 5501 SDValue Ops[] = { CurDAG->getTargetConstant(SYSmValue, DL, MVT::i32), 5502 getAL(CurDAG, DL), CurDAG->getRegister(0, MVT::i32), 5503 N->getOperand(0) }; 5504 ReplaceNode( 5505 N, CurDAG->getMachineNode(ARM::t2MRS_M, DL, MVT::i32, MVT::Other, Ops)); 5506 return true; 5507 } 5508 5509 // Here we know the target is not M Class so we need to check if it is one 5510 // of the remaining possible values which are apsr, cpsr or spsr. 5511 if (SpecialReg == "apsr" || SpecialReg == "cpsr") { 5512 Ops = { getAL(CurDAG, DL), CurDAG->getRegister(0, MVT::i32), 5513 N->getOperand(0) }; 5514 ReplaceNode(N, CurDAG->getMachineNode(IsThumb2 ? ARM::t2MRS_AR : ARM::MRS, 5515 DL, MVT::i32, MVT::Other, Ops)); 5516 return true; 5517 } 5518 5519 if (SpecialReg == "spsr") { 5520 Ops = { getAL(CurDAG, DL), CurDAG->getRegister(0, MVT::i32), 5521 N->getOperand(0) }; 5522 ReplaceNode( 5523 N, CurDAG->getMachineNode(IsThumb2 ? ARM::t2MRSsys_AR : ARM::MRSsys, DL, 5524 MVT::i32, MVT::Other, Ops)); 5525 return true; 5526 } 5527 5528 return false; 5529 } 5530 5531 // Lower the write_register intrinsic to ARM specific DAG nodes 5532 // using the supplied metadata string to select the instruction node to use 5533 // and the registers/masks to use in the nodes 5534 bool ARMDAGToDAGISel::tryWriteRegister(SDNode *N){ 5535 const MDNodeSDNode *MD = dyn_cast<MDNodeSDNode>(N->getOperand(1)); 5536 const MDString *RegString = dyn_cast<MDString>(MD->getMD()->getOperand(0)); 5537 bool IsThumb2 = Subtarget->isThumb2(); 5538 SDLoc DL(N); 5539 5540 std::vector<SDValue> Ops; 5541 getIntOperandsFromRegisterString(RegString->getString(), CurDAG, DL, Ops); 5542 5543 if (!Ops.empty()) { 5544 // If the special register string was constructed of fields (as defined 5545 // in the ACLE) then need to lower to MCR node (32 bit) or 5546 // MCRR node(64 bit), we can make the distinction based on the number of 5547 // operands we have. 5548 unsigned Opcode; 5549 if (Ops.size() == 5) { 5550 Opcode = IsThumb2 ? ARM::t2MCR : ARM::MCR; 5551 Ops.insert(Ops.begin()+2, N->getOperand(2)); 5552 } else { 5553 assert(Ops.size() == 3 && 5554 "Invalid number of fields in special register string."); 5555 Opcode = IsThumb2 ? ARM::t2MCRR : ARM::MCRR; 5556 SDValue WriteValue[] = { N->getOperand(2), N->getOperand(3) }; 5557 Ops.insert(Ops.begin()+2, WriteValue, WriteValue+2); 5558 } 5559 5560 Ops.push_back(getAL(CurDAG, DL)); 5561 Ops.push_back(CurDAG->getRegister(0, MVT::i32)); 5562 Ops.push_back(N->getOperand(0)); 5563 5564 ReplaceNode(N, CurDAG->getMachineNode(Opcode, DL, MVT::Other, Ops)); 5565 return true; 5566 } 5567 5568 std::string SpecialReg = RegString->getString().lower(); 5569 int BankedReg = getBankedRegisterMask(SpecialReg); 5570 if (BankedReg != -1) { 5571 Ops = { CurDAG->getTargetConstant(BankedReg, DL, MVT::i32), N->getOperand(2), 5572 getAL(CurDAG, DL), CurDAG->getRegister(0, MVT::i32), 5573 N->getOperand(0) }; 5574 ReplaceNode( 5575 N, CurDAG->getMachineNode(IsThumb2 ? ARM::t2MSRbanked : ARM::MSRbanked, 5576 DL, MVT::Other, Ops)); 5577 return true; 5578 } 5579 5580 // The VFP registers are written to by creating SelectionDAG nodes with 5581 // opcodes corresponding to the register that is being written. So we switch 5582 // on the string to find which opcode we need to use. 5583 unsigned Opcode = StringSwitch<unsigned>(SpecialReg) 5584 .Case("fpscr", ARM::VMSR) 5585 .Case("fpexc", ARM::VMSR_FPEXC) 5586 .Case("fpsid", ARM::VMSR_FPSID) 5587 .Case("fpinst", ARM::VMSR_FPINST) 5588 .Case("fpinst2", ARM::VMSR_FPINST2) 5589 .Default(0); 5590 5591 if (Opcode) { 5592 if (!Subtarget->hasVFP2Base()) 5593 return false; 5594 Ops = { N->getOperand(2), getAL(CurDAG, DL), 5595 CurDAG->getRegister(0, MVT::i32), N->getOperand(0) }; 5596 ReplaceNode(N, CurDAG->getMachineNode(Opcode, DL, MVT::Other, Ops)); 5597 return true; 5598 } 5599 5600 std::pair<StringRef, StringRef> Fields; 5601 Fields = StringRef(SpecialReg).rsplit('_'); 5602 std::string Reg = Fields.first.str(); 5603 StringRef Flags = Fields.second; 5604 5605 // If the target was M Class then need to validate the special register value 5606 // and retrieve the mask for use in the instruction node. 5607 if (Subtarget->isMClass()) { 5608 int SYSmValue = getMClassRegisterMask(SpecialReg, Subtarget); 5609 if (SYSmValue == -1) 5610 return false; 5611 5612 SDValue Ops[] = { CurDAG->getTargetConstant(SYSmValue, DL, MVT::i32), 5613 N->getOperand(2), getAL(CurDAG, DL), 5614 CurDAG->getRegister(0, MVT::i32), N->getOperand(0) }; 5615 ReplaceNode(N, CurDAG->getMachineNode(ARM::t2MSR_M, DL, MVT::Other, Ops)); 5616 return true; 5617 } 5618 5619 // We then check to see if a valid mask can be constructed for one of the 5620 // register string values permitted for the A and R class cores. These values 5621 // are apsr, spsr and cpsr; these are also valid on older cores. 5622 int Mask = getARClassRegisterMask(Reg, Flags); 5623 if (Mask != -1) { 5624 Ops = { CurDAG->getTargetConstant(Mask, DL, MVT::i32), N->getOperand(2), 5625 getAL(CurDAG, DL), CurDAG->getRegister(0, MVT::i32), 5626 N->getOperand(0) }; 5627 ReplaceNode(N, CurDAG->getMachineNode(IsThumb2 ? ARM::t2MSR_AR : ARM::MSR, 5628 DL, MVT::Other, Ops)); 5629 return true; 5630 } 5631 5632 return false; 5633 } 5634 5635 bool ARMDAGToDAGISel::tryInlineAsm(SDNode *N){ 5636 std::vector<SDValue> AsmNodeOperands; 5637 unsigned Flag, Kind; 5638 bool Changed = false; 5639 unsigned NumOps = N->getNumOperands(); 5640 5641 // Normally, i64 data is bounded to two arbitrary GRPs for "%r" constraint. 5642 // However, some instrstions (e.g. ldrexd/strexd in ARM mode) require 5643 // (even/even+1) GPRs and use %n and %Hn to refer to the individual regs 5644 // respectively. Since there is no constraint to explicitly specify a 5645 // reg pair, we use GPRPair reg class for "%r" for 64-bit data. For Thumb, 5646 // the 64-bit data may be referred by H, Q, R modifiers, so we still pack 5647 // them into a GPRPair. 5648 5649 SDLoc dl(N); 5650 SDValue Glue = N->getGluedNode() ? N->getOperand(NumOps-1) 5651 : SDValue(nullptr,0); 5652 5653 SmallVector<bool, 8> OpChanged; 5654 // Glue node will be appended late. 5655 for(unsigned i = 0, e = N->getGluedNode() ? NumOps - 1 : NumOps; i < e; ++i) { 5656 SDValue op = N->getOperand(i); 5657 AsmNodeOperands.push_back(op); 5658 5659 if (i < InlineAsm::Op_FirstOperand) 5660 continue; 5661 5662 if (ConstantSDNode *C = dyn_cast<ConstantSDNode>(N->getOperand(i))) { 5663 Flag = C->getZExtValue(); 5664 Kind = InlineAsm::getKind(Flag); 5665 } 5666 else 5667 continue; 5668 5669 // Immediate operands to inline asm in the SelectionDAG are modeled with 5670 // two operands. The first is a constant of value InlineAsm::Kind_Imm, and 5671 // the second is a constant with the value of the immediate. If we get here 5672 // and we have a Kind_Imm, skip the next operand, and continue. 5673 if (Kind == InlineAsm::Kind_Imm) { 5674 SDValue op = N->getOperand(++i); 5675 AsmNodeOperands.push_back(op); 5676 continue; 5677 } 5678 5679 unsigned NumRegs = InlineAsm::getNumOperandRegisters(Flag); 5680 if (NumRegs) 5681 OpChanged.push_back(false); 5682 5683 unsigned DefIdx = 0; 5684 bool IsTiedToChangedOp = false; 5685 // If it's a use that is tied with a previous def, it has no 5686 // reg class constraint. 5687 if (Changed && InlineAsm::isUseOperandTiedToDef(Flag, DefIdx)) 5688 IsTiedToChangedOp = OpChanged[DefIdx]; 5689 5690 // Memory operands to inline asm in the SelectionDAG are modeled with two 5691 // operands: a constant of value InlineAsm::Kind_Mem followed by the input 5692 // operand. If we get here and we have a Kind_Mem, skip the next operand (so 5693 // it doesn't get misinterpreted), and continue. We do this here because 5694 // it's important to update the OpChanged array correctly before moving on. 5695 if (Kind == InlineAsm::Kind_Mem) { 5696 SDValue op = N->getOperand(++i); 5697 AsmNodeOperands.push_back(op); 5698 continue; 5699 } 5700 5701 if (Kind != InlineAsm::Kind_RegUse && Kind != InlineAsm::Kind_RegDef 5702 && Kind != InlineAsm::Kind_RegDefEarlyClobber) 5703 continue; 5704 5705 unsigned RC; 5706 bool HasRC = InlineAsm::hasRegClassConstraint(Flag, RC); 5707 if ((!IsTiedToChangedOp && (!HasRC || RC != ARM::GPRRegClassID)) 5708 || NumRegs != 2) 5709 continue; 5710 5711 assert((i+2 < NumOps) && "Invalid number of operands in inline asm"); 5712 SDValue V0 = N->getOperand(i+1); 5713 SDValue V1 = N->getOperand(i+2); 5714 unsigned Reg0 = cast<RegisterSDNode>(V0)->getReg(); 5715 unsigned Reg1 = cast<RegisterSDNode>(V1)->getReg(); 5716 SDValue PairedReg; 5717 MachineRegisterInfo &MRI = MF->getRegInfo(); 5718 5719 if (Kind == InlineAsm::Kind_RegDef || 5720 Kind == InlineAsm::Kind_RegDefEarlyClobber) { 5721 // Replace the two GPRs with 1 GPRPair and copy values from GPRPair to 5722 // the original GPRs. 5723 5724 Register GPVR = MRI.createVirtualRegister(&ARM::GPRPairRegClass); 5725 PairedReg = CurDAG->getRegister(GPVR, MVT::Untyped); 5726 SDValue Chain = SDValue(N,0); 5727 5728 SDNode *GU = N->getGluedUser(); 5729 SDValue RegCopy = CurDAG->getCopyFromReg(Chain, dl, GPVR, MVT::Untyped, 5730 Chain.getValue(1)); 5731 5732 // Extract values from a GPRPair reg and copy to the original GPR reg. 5733 SDValue Sub0 = CurDAG->getTargetExtractSubreg(ARM::gsub_0, dl, MVT::i32, 5734 RegCopy); 5735 SDValue Sub1 = CurDAG->getTargetExtractSubreg(ARM::gsub_1, dl, MVT::i32, 5736 RegCopy); 5737 SDValue T0 = CurDAG->getCopyToReg(Sub0, dl, Reg0, Sub0, 5738 RegCopy.getValue(1)); 5739 SDValue T1 = CurDAG->getCopyToReg(Sub1, dl, Reg1, Sub1, T0.getValue(1)); 5740 5741 // Update the original glue user. 5742 std::vector<SDValue> Ops(GU->op_begin(), GU->op_end()-1); 5743 Ops.push_back(T1.getValue(1)); 5744 CurDAG->UpdateNodeOperands(GU, Ops); 5745 } 5746 else { 5747 // For Kind == InlineAsm::Kind_RegUse, we first copy two GPRs into a 5748 // GPRPair and then pass the GPRPair to the inline asm. 5749 SDValue Chain = AsmNodeOperands[InlineAsm::Op_InputChain]; 5750 5751 // As REG_SEQ doesn't take RegisterSDNode, we copy them first. 5752 SDValue T0 = CurDAG->getCopyFromReg(Chain, dl, Reg0, MVT::i32, 5753 Chain.getValue(1)); 5754 SDValue T1 = CurDAG->getCopyFromReg(Chain, dl, Reg1, MVT::i32, 5755 T0.getValue(1)); 5756 SDValue Pair = SDValue(createGPRPairNode(MVT::Untyped, T0, T1), 0); 5757 5758 // Copy REG_SEQ into a GPRPair-typed VR and replace the original two 5759 // i32 VRs of inline asm with it. 5760 Register GPVR = MRI.createVirtualRegister(&ARM::GPRPairRegClass); 5761 PairedReg = CurDAG->getRegister(GPVR, MVT::Untyped); 5762 Chain = CurDAG->getCopyToReg(T1, dl, GPVR, Pair, T1.getValue(1)); 5763 5764 AsmNodeOperands[InlineAsm::Op_InputChain] = Chain; 5765 Glue = Chain.getValue(1); 5766 } 5767 5768 Changed = true; 5769 5770 if(PairedReg.getNode()) { 5771 OpChanged[OpChanged.size() -1 ] = true; 5772 Flag = InlineAsm::getFlagWord(Kind, 1 /* RegNum*/); 5773 if (IsTiedToChangedOp) 5774 Flag = InlineAsm::getFlagWordForMatchingOp(Flag, DefIdx); 5775 else 5776 Flag = InlineAsm::getFlagWordForRegClass(Flag, ARM::GPRPairRegClassID); 5777 // Replace the current flag. 5778 AsmNodeOperands[AsmNodeOperands.size() -1] = CurDAG->getTargetConstant( 5779 Flag, dl, MVT::i32); 5780 // Add the new register node and skip the original two GPRs. 5781 AsmNodeOperands.push_back(PairedReg); 5782 // Skip the next two GPRs. 5783 i += 2; 5784 } 5785 } 5786 5787 if (Glue.getNode()) 5788 AsmNodeOperands.push_back(Glue); 5789 if (!Changed) 5790 return false; 5791 5792 SDValue New = CurDAG->getNode(N->getOpcode(), SDLoc(N), 5793 CurDAG->getVTList(MVT::Other, MVT::Glue), AsmNodeOperands); 5794 New->setNodeId(-1); 5795 ReplaceNode(N, New.getNode()); 5796 return true; 5797 } 5798 5799 5800 bool ARMDAGToDAGISel:: 5801 SelectInlineAsmMemoryOperand(const SDValue &Op, unsigned ConstraintID, 5802 std::vector<SDValue> &OutOps) { 5803 switch(ConstraintID) { 5804 default: 5805 llvm_unreachable("Unexpected asm memory constraint"); 5806 case InlineAsm::Constraint_m: 5807 case InlineAsm::Constraint_o: 5808 case InlineAsm::Constraint_Q: 5809 case InlineAsm::Constraint_Um: 5810 case InlineAsm::Constraint_Un: 5811 case InlineAsm::Constraint_Uq: 5812 case InlineAsm::Constraint_Us: 5813 case InlineAsm::Constraint_Ut: 5814 case InlineAsm::Constraint_Uv: 5815 case InlineAsm::Constraint_Uy: 5816 // Require the address to be in a register. That is safe for all ARM 5817 // variants and it is hard to do anything much smarter without knowing 5818 // how the operand is used. 5819 OutOps.push_back(Op); 5820 return false; 5821 } 5822 return true; 5823 } 5824 5825 /// createARMISelDag - This pass converts a legalized DAG into a 5826 /// ARM-specific DAG, ready for instruction scheduling. 5827 /// 5828 FunctionPass *llvm::createARMISelDag(ARMBaseTargetMachine &TM, 5829 CodeGenOpt::Level OptLevel) { 5830 return new ARMDAGToDAGISel(TM, OptLevel); 5831 } 5832