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