LLVM API Documentation
00001 //===-- ARMISelDAGToDAG.cpp - A dag to dag inst selector for ARM ----------===// 00002 // 00003 // The LLVM Compiler Infrastructure 00004 // 00005 // This file is distributed under the University of Illinois Open Source 00006 // License. See LICENSE.TXT for details. 00007 // 00008 //===----------------------------------------------------------------------===// 00009 // 00010 // This file defines an instruction selector for the ARM target. 00011 // 00012 //===----------------------------------------------------------------------===// 00013 00014 #include "ARM.h" 00015 #include "ARMBaseInstrInfo.h" 00016 #include "ARMTargetMachine.h" 00017 #include "MCTargetDesc/ARMAddressingModes.h" 00018 #include "llvm/CodeGen/MachineFrameInfo.h" 00019 #include "llvm/CodeGen/MachineFunction.h" 00020 #include "llvm/CodeGen/MachineInstrBuilder.h" 00021 #include "llvm/CodeGen/MachineRegisterInfo.h" 00022 #include "llvm/CodeGen/SelectionDAG.h" 00023 #include "llvm/CodeGen/SelectionDAGISel.h" 00024 #include "llvm/IR/CallingConv.h" 00025 #include "llvm/IR/Constants.h" 00026 #include "llvm/IR/DerivedTypes.h" 00027 #include "llvm/IR/Function.h" 00028 #include "llvm/IR/Intrinsics.h" 00029 #include "llvm/IR/LLVMContext.h" 00030 #include "llvm/Support/CommandLine.h" 00031 #include "llvm/Support/Compiler.h" 00032 #include "llvm/Support/Debug.h" 00033 #include "llvm/Support/ErrorHandling.h" 00034 #include "llvm/Target/TargetLowering.h" 00035 #include "llvm/Target/TargetOptions.h" 00036 00037 using namespace llvm; 00038 00039 #define DEBUG_TYPE "arm-isel" 00040 00041 static cl::opt<bool> 00042 DisableShifterOp("disable-shifter-op", cl::Hidden, 00043 cl::desc("Disable isel of shifter-op"), 00044 cl::init(false)); 00045 00046 static cl::opt<bool> 00047 CheckVMLxHazard("check-vmlx-hazard", cl::Hidden, 00048 cl::desc("Check fp vmla / vmls hazard at isel time"), 00049 cl::init(true)); 00050 00051 //===--------------------------------------------------------------------===// 00052 /// ARMDAGToDAGISel - ARM specific code to select ARM machine 00053 /// instructions for SelectionDAG operations. 00054 /// 00055 namespace { 00056 00057 enum AddrMode2Type { 00058 AM2_BASE, // Simple AM2 (+-imm12) 00059 AM2_SHOP // Shifter-op AM2 00060 }; 00061 00062 class ARMDAGToDAGISel : public SelectionDAGISel { 00063 /// Subtarget - Keep a pointer to the ARMSubtarget around so that we can 00064 /// make the right decision when generating code for different targets. 00065 const ARMSubtarget *Subtarget; 00066 00067 public: 00068 explicit ARMDAGToDAGISel(ARMBaseTargetMachine &tm, CodeGenOpt::Level OptLevel) 00069 : SelectionDAGISel(tm, OptLevel) {} 00070 00071 bool runOnMachineFunction(MachineFunction &MF) override { 00072 // Reset the subtarget each time through. 00073 Subtarget = &MF.getTarget().getSubtarget<ARMSubtarget>(); 00074 SelectionDAGISel::runOnMachineFunction(MF); 00075 return true; 00076 } 00077 00078 const char *getPassName() const override { 00079 return "ARM Instruction Selection"; 00080 } 00081 00082 void PreprocessISelDAG() override; 00083 00084 /// getI32Imm - Return a target constant of type i32 with the specified 00085 /// value. 00086 inline SDValue getI32Imm(unsigned Imm) { 00087 return CurDAG->getTargetConstant(Imm, MVT::i32); 00088 } 00089 00090 SDNode *Select(SDNode *N) override; 00091 00092 00093 bool hasNoVMLxHazardUse(SDNode *N) const; 00094 bool isShifterOpProfitable(const SDValue &Shift, 00095 ARM_AM::ShiftOpc ShOpcVal, unsigned ShAmt); 00096 bool SelectRegShifterOperand(SDValue N, SDValue &A, 00097 SDValue &B, SDValue &C, 00098 bool CheckProfitability = true); 00099 bool SelectImmShifterOperand(SDValue N, SDValue &A, 00100 SDValue &B, bool CheckProfitability = true); 00101 bool SelectShiftRegShifterOperand(SDValue N, SDValue &A, 00102 SDValue &B, SDValue &C) { 00103 // Don't apply the profitability check 00104 return SelectRegShifterOperand(N, A, B, C, false); 00105 } 00106 bool SelectShiftImmShifterOperand(SDValue N, SDValue &A, 00107 SDValue &B) { 00108 // Don't apply the profitability check 00109 return SelectImmShifterOperand(N, A, B, false); 00110 } 00111 00112 bool SelectAddrModeImm12(SDValue N, SDValue &Base, SDValue &OffImm); 00113 bool SelectLdStSOReg(SDValue N, SDValue &Base, SDValue &Offset, SDValue &Opc); 00114 00115 AddrMode2Type SelectAddrMode2Worker(SDValue N, SDValue &Base, 00116 SDValue &Offset, SDValue &Opc); 00117 bool SelectAddrMode2Base(SDValue N, SDValue &Base, SDValue &Offset, 00118 SDValue &Opc) { 00119 return SelectAddrMode2Worker(N, Base, Offset, Opc) == AM2_BASE; 00120 } 00121 00122 bool SelectAddrMode2ShOp(SDValue N, SDValue &Base, SDValue &Offset, 00123 SDValue &Opc) { 00124 return SelectAddrMode2Worker(N, Base, Offset, Opc) == AM2_SHOP; 00125 } 00126 00127 bool SelectAddrMode2(SDValue N, SDValue &Base, SDValue &Offset, 00128 SDValue &Opc) { 00129 SelectAddrMode2Worker(N, Base, Offset, Opc); 00130 // return SelectAddrMode2ShOp(N, Base, Offset, Opc); 00131 // This always matches one way or another. 00132 return true; 00133 } 00134 00135 bool SelectCMOVPred(SDValue N, SDValue &Pred, SDValue &Reg) { 00136 const ConstantSDNode *CN = cast<ConstantSDNode>(N); 00137 Pred = CurDAG->getTargetConstant(CN->getZExtValue(), MVT::i32); 00138 Reg = CurDAG->getRegister(ARM::CPSR, MVT::i32); 00139 return true; 00140 } 00141 00142 bool SelectAddrMode2OffsetReg(SDNode *Op, SDValue N, 00143 SDValue &Offset, SDValue &Opc); 00144 bool SelectAddrMode2OffsetImm(SDNode *Op, SDValue N, 00145 SDValue &Offset, SDValue &Opc); 00146 bool SelectAddrMode2OffsetImmPre(SDNode *Op, SDValue N, 00147 SDValue &Offset, SDValue &Opc); 00148 bool SelectAddrOffsetNone(SDValue N, SDValue &Base); 00149 bool SelectAddrMode3(SDValue N, SDValue &Base, 00150 SDValue &Offset, SDValue &Opc); 00151 bool SelectAddrMode3Offset(SDNode *Op, SDValue N, 00152 SDValue &Offset, SDValue &Opc); 00153 bool SelectAddrMode5(SDValue N, SDValue &Base, 00154 SDValue &Offset); 00155 bool SelectAddrMode6(SDNode *Parent, SDValue N, SDValue &Addr,SDValue &Align); 00156 bool SelectAddrMode6Offset(SDNode *Op, SDValue N, SDValue &Offset); 00157 00158 bool SelectAddrModePC(SDValue N, SDValue &Offset, SDValue &Label); 00159 00160 // Thumb Addressing Modes: 00161 bool SelectThumbAddrModeRR(SDValue N, SDValue &Base, SDValue &Offset); 00162 bool SelectThumbAddrModeRI(SDValue N, SDValue &Base, SDValue &Offset, 00163 unsigned Scale); 00164 bool SelectThumbAddrModeRI5S1(SDValue N, SDValue &Base, SDValue &Offset); 00165 bool SelectThumbAddrModeRI5S2(SDValue N, SDValue &Base, SDValue &Offset); 00166 bool SelectThumbAddrModeRI5S4(SDValue N, SDValue &Base, SDValue &Offset); 00167 bool SelectThumbAddrModeImm5S(SDValue N, unsigned Scale, SDValue &Base, 00168 SDValue &OffImm); 00169 bool SelectThumbAddrModeImm5S1(SDValue N, SDValue &Base, 00170 SDValue &OffImm); 00171 bool SelectThumbAddrModeImm5S2(SDValue N, SDValue &Base, 00172 SDValue &OffImm); 00173 bool SelectThumbAddrModeImm5S4(SDValue N, SDValue &Base, 00174 SDValue &OffImm); 00175 bool SelectThumbAddrModeSP(SDValue N, SDValue &Base, SDValue &OffImm); 00176 00177 // Thumb 2 Addressing Modes: 00178 bool SelectT2ShifterOperandReg(SDValue N, 00179 SDValue &BaseReg, SDValue &Opc); 00180 bool SelectT2AddrModeImm12(SDValue N, SDValue &Base, SDValue &OffImm); 00181 bool SelectT2AddrModeImm8(SDValue N, SDValue &Base, 00182 SDValue &OffImm); 00183 bool SelectT2AddrModeImm8Offset(SDNode *Op, SDValue N, 00184 SDValue &OffImm); 00185 bool SelectT2AddrModeSoReg(SDValue N, SDValue &Base, 00186 SDValue &OffReg, SDValue &ShImm); 00187 bool SelectT2AddrModeExclusive(SDValue N, SDValue &Base, SDValue &OffImm); 00188 00189 inline bool is_so_imm(unsigned Imm) const { 00190 return ARM_AM::getSOImmVal(Imm) != -1; 00191 } 00192 00193 inline bool is_so_imm_not(unsigned Imm) const { 00194 return ARM_AM::getSOImmVal(~Imm) != -1; 00195 } 00196 00197 inline bool is_t2_so_imm(unsigned Imm) const { 00198 return ARM_AM::getT2SOImmVal(Imm) != -1; 00199 } 00200 00201 inline bool is_t2_so_imm_not(unsigned Imm) const { 00202 return ARM_AM::getT2SOImmVal(~Imm) != -1; 00203 } 00204 00205 // Include the pieces autogenerated from the target description. 00206 #include "ARMGenDAGISel.inc" 00207 00208 private: 00209 /// SelectARMIndexedLoad - Indexed (pre/post inc/dec) load matching code for 00210 /// ARM. 00211 SDNode *SelectARMIndexedLoad(SDNode *N); 00212 SDNode *SelectT2IndexedLoad(SDNode *N); 00213 00214 /// SelectVLD - Select NEON load intrinsics. NumVecs should be 00215 /// 1, 2, 3 or 4. The opcode arrays specify the instructions used for 00216 /// loads of D registers and even subregs and odd subregs of Q registers. 00217 /// For NumVecs <= 2, QOpcodes1 is not used. 00218 SDNode *SelectVLD(SDNode *N, bool isUpdating, unsigned NumVecs, 00219 const uint16_t *DOpcodes, 00220 const uint16_t *QOpcodes0, const uint16_t *QOpcodes1); 00221 00222 /// SelectVST - Select NEON store intrinsics. NumVecs should 00223 /// be 1, 2, 3 or 4. The opcode arrays specify the instructions used for 00224 /// stores of D registers and even subregs and odd subregs of Q registers. 00225 /// For NumVecs <= 2, QOpcodes1 is not used. 00226 SDNode *SelectVST(SDNode *N, bool isUpdating, unsigned NumVecs, 00227 const uint16_t *DOpcodes, 00228 const uint16_t *QOpcodes0, const uint16_t *QOpcodes1); 00229 00230 /// SelectVLDSTLane - Select NEON load/store lane intrinsics. NumVecs should 00231 /// be 2, 3 or 4. The opcode arrays specify the instructions used for 00232 /// load/store of D registers and Q registers. 00233 SDNode *SelectVLDSTLane(SDNode *N, bool IsLoad, 00234 bool isUpdating, unsigned NumVecs, 00235 const uint16_t *DOpcodes, const uint16_t *QOpcodes); 00236 00237 /// SelectVLDDup - Select NEON load-duplicate intrinsics. NumVecs 00238 /// should be 2, 3 or 4. The opcode array specifies the instructions used 00239 /// for loading D registers. (Q registers are not supported.) 00240 SDNode *SelectVLDDup(SDNode *N, bool isUpdating, unsigned NumVecs, 00241 const uint16_t *Opcodes); 00242 00243 /// SelectVTBL - Select NEON VTBL and VTBX intrinsics. NumVecs should be 2, 00244 /// 3 or 4. These are custom-selected so that a REG_SEQUENCE can be 00245 /// generated to force the table registers to be consecutive. 00246 SDNode *SelectVTBL(SDNode *N, bool IsExt, unsigned NumVecs, unsigned Opc); 00247 00248 /// SelectV6T2BitfieldExtractOp - Select SBFX/UBFX instructions for ARM. 00249 SDNode *SelectV6T2BitfieldExtractOp(SDNode *N, bool isSigned); 00250 00251 // Select special operations if node forms integer ABS pattern 00252 SDNode *SelectABSOp(SDNode *N); 00253 00254 SDNode *SelectInlineAsm(SDNode *N); 00255 00256 SDNode *SelectConcatVector(SDNode *N); 00257 00258 /// SelectInlineAsmMemoryOperand - Implement addressing mode selection for 00259 /// inline asm expressions. 00260 bool SelectInlineAsmMemoryOperand(const SDValue &Op, char ConstraintCode, 00261 std::vector<SDValue> &OutOps) override; 00262 00263 // Form pairs of consecutive R, S, D, or Q registers. 00264 SDNode *createGPRPairNode(EVT VT, SDValue V0, SDValue V1); 00265 SDNode *createSRegPairNode(EVT VT, SDValue V0, SDValue V1); 00266 SDNode *createDRegPairNode(EVT VT, SDValue V0, SDValue V1); 00267 SDNode *createQRegPairNode(EVT VT, SDValue V0, SDValue V1); 00268 00269 // Form sequences of 4 consecutive S, D, or Q registers. 00270 SDNode *createQuadSRegsNode(EVT VT, SDValue V0, SDValue V1, SDValue V2, SDValue V3); 00271 SDNode *createQuadDRegsNode(EVT VT, SDValue V0, SDValue V1, SDValue V2, SDValue V3); 00272 SDNode *createQuadQRegsNode(EVT VT, SDValue V0, SDValue V1, SDValue V2, SDValue V3); 00273 00274 // Get the alignment operand for a NEON VLD or VST instruction. 00275 SDValue GetVLDSTAlign(SDValue Align, unsigned NumVecs, bool is64BitVector); 00276 }; 00277 } 00278 00279 /// isInt32Immediate - This method tests to see if the node is a 32-bit constant 00280 /// operand. If so Imm will receive the 32-bit value. 00281 static bool isInt32Immediate(SDNode *N, unsigned &Imm) { 00282 if (N->getOpcode() == ISD::Constant && N->getValueType(0) == MVT::i32) { 00283 Imm = cast<ConstantSDNode>(N)->getZExtValue(); 00284 return true; 00285 } 00286 return false; 00287 } 00288 00289 // isInt32Immediate - This method tests to see if a constant operand. 00290 // If so Imm will receive the 32 bit value. 00291 static bool isInt32Immediate(SDValue N, unsigned &Imm) { 00292 return isInt32Immediate(N.getNode(), Imm); 00293 } 00294 00295 // isOpcWithIntImmediate - This method tests to see if the node is a specific 00296 // opcode and that it has a immediate integer right operand. 00297 // If so Imm will receive the 32 bit value. 00298 static bool isOpcWithIntImmediate(SDNode *N, unsigned Opc, unsigned& Imm) { 00299 return N->getOpcode() == Opc && 00300 isInt32Immediate(N->getOperand(1).getNode(), Imm); 00301 } 00302 00303 /// \brief Check whether a particular node is a constant value representable as 00304 /// (N * Scale) where (N in [\p RangeMin, \p RangeMax). 00305 /// 00306 /// \param ScaledConstant [out] - On success, the pre-scaled constant value. 00307 static bool isScaledConstantInRange(SDValue Node, int Scale, 00308 int RangeMin, int RangeMax, 00309 int &ScaledConstant) { 00310 assert(Scale > 0 && "Invalid scale!"); 00311 00312 // Check that this is a constant. 00313 const ConstantSDNode *C = dyn_cast<ConstantSDNode>(Node); 00314 if (!C) 00315 return false; 00316 00317 ScaledConstant = (int) C->getZExtValue(); 00318 if ((ScaledConstant % Scale) != 0) 00319 return false; 00320 00321 ScaledConstant /= Scale; 00322 return ScaledConstant >= RangeMin && ScaledConstant < RangeMax; 00323 } 00324 00325 void ARMDAGToDAGISel::PreprocessISelDAG() { 00326 if (!Subtarget->hasV6T2Ops()) 00327 return; 00328 00329 bool isThumb2 = Subtarget->isThumb(); 00330 for (SelectionDAG::allnodes_iterator I = CurDAG->allnodes_begin(), 00331 E = CurDAG->allnodes_end(); I != E; ) { 00332 SDNode *N = I++; // Preincrement iterator to avoid invalidation issues. 00333 00334 if (N->getOpcode() != ISD::ADD) 00335 continue; 00336 00337 // Look for (add X1, (and (srl X2, c1), c2)) where c2 is constant with 00338 // leading zeros, followed by consecutive set bits, followed by 1 or 2 00339 // trailing zeros, e.g. 1020. 00340 // Transform the expression to 00341 // (add X1, (shl (and (srl X2, c1), (c2>>tz)), tz)) where tz is the number 00342 // of trailing zeros of c2. The left shift would be folded as an shifter 00343 // operand of 'add' and the 'and' and 'srl' would become a bits extraction 00344 // node (UBFX). 00345 00346 SDValue N0 = N->getOperand(0); 00347 SDValue N1 = N->getOperand(1); 00348 unsigned And_imm = 0; 00349 if (!isOpcWithIntImmediate(N1.getNode(), ISD::AND, And_imm)) { 00350 if (isOpcWithIntImmediate(N0.getNode(), ISD::AND, And_imm)) 00351 std::swap(N0, N1); 00352 } 00353 if (!And_imm) 00354 continue; 00355 00356 // Check if the AND mask is an immediate of the form: 000.....1111111100 00357 unsigned TZ = countTrailingZeros(And_imm); 00358 if (TZ != 1 && TZ != 2) 00359 // Be conservative here. Shifter operands aren't always free. e.g. On 00360 // Swift, left shifter operand of 1 / 2 for free but others are not. 00361 // e.g. 00362 // ubfx r3, r1, #16, #8 00363 // ldr.w r3, [r0, r3, lsl #2] 00364 // vs. 00365 // mov.w r9, #1020 00366 // and.w r2, r9, r1, lsr #14 00367 // ldr r2, [r0, r2] 00368 continue; 00369 And_imm >>= TZ; 00370 if (And_imm & (And_imm + 1)) 00371 continue; 00372 00373 // Look for (and (srl X, c1), c2). 00374 SDValue Srl = N1.getOperand(0); 00375 unsigned Srl_imm = 0; 00376 if (!isOpcWithIntImmediate(Srl.getNode(), ISD::SRL, Srl_imm) || 00377 (Srl_imm <= 2)) 00378 continue; 00379 00380 // Make sure first operand is not a shifter operand which would prevent 00381 // folding of the left shift. 00382 SDValue CPTmp0; 00383 SDValue CPTmp1; 00384 SDValue CPTmp2; 00385 if (isThumb2) { 00386 if (SelectT2ShifterOperandReg(N0, CPTmp0, CPTmp1)) 00387 continue; 00388 } else { 00389 if (SelectImmShifterOperand(N0, CPTmp0, CPTmp1) || 00390 SelectRegShifterOperand(N0, CPTmp0, CPTmp1, CPTmp2)) 00391 continue; 00392 } 00393 00394 // Now make the transformation. 00395 Srl = CurDAG->getNode(ISD::SRL, SDLoc(Srl), MVT::i32, 00396 Srl.getOperand(0), 00397 CurDAG->getConstant(Srl_imm+TZ, MVT::i32)); 00398 N1 = CurDAG->getNode(ISD::AND, SDLoc(N1), MVT::i32, 00399 Srl, CurDAG->getConstant(And_imm, MVT::i32)); 00400 N1 = CurDAG->getNode(ISD::SHL, SDLoc(N1), MVT::i32, 00401 N1, CurDAG->getConstant(TZ, MVT::i32)); 00402 CurDAG->UpdateNodeOperands(N, N0, N1); 00403 } 00404 } 00405 00406 /// hasNoVMLxHazardUse - Return true if it's desirable to select a FP MLA / MLS 00407 /// node. VFP / NEON fp VMLA / VMLS instructions have special RAW hazards (at 00408 /// least on current ARM implementations) which should be avoidded. 00409 bool ARMDAGToDAGISel::hasNoVMLxHazardUse(SDNode *N) const { 00410 if (OptLevel == CodeGenOpt::None) 00411 return true; 00412 00413 if (!CheckVMLxHazard) 00414 return true; 00415 00416 if (!Subtarget->isCortexA7() && !Subtarget->isCortexA8() && 00417 !Subtarget->isCortexA9() && !Subtarget->isSwift()) 00418 return true; 00419 00420 if (!N->hasOneUse()) 00421 return false; 00422 00423 SDNode *Use = *N->use_begin(); 00424 if (Use->getOpcode() == ISD::CopyToReg) 00425 return true; 00426 if (Use->isMachineOpcode()) { 00427 const ARMBaseInstrInfo *TII = static_cast<const ARMBaseInstrInfo *>( 00428 CurDAG->getSubtarget().getInstrInfo()); 00429 00430 const MCInstrDesc &MCID = TII->get(Use->getMachineOpcode()); 00431 if (MCID.mayStore()) 00432 return true; 00433 unsigned Opcode = MCID.getOpcode(); 00434 if (Opcode == ARM::VMOVRS || Opcode == ARM::VMOVRRD) 00435 return true; 00436 // vmlx feeding into another vmlx. We actually want to unfold 00437 // the use later in the MLxExpansion pass. e.g. 00438 // vmla 00439 // vmla (stall 8 cycles) 00440 // 00441 // vmul (5 cycles) 00442 // vadd (5 cycles) 00443 // vmla 00444 // This adds up to about 18 - 19 cycles. 00445 // 00446 // vmla 00447 // vmul (stall 4 cycles) 00448 // vadd adds up to about 14 cycles. 00449 return TII->isFpMLxInstruction(Opcode); 00450 } 00451 00452 return false; 00453 } 00454 00455 bool ARMDAGToDAGISel::isShifterOpProfitable(const SDValue &Shift, 00456 ARM_AM::ShiftOpc ShOpcVal, 00457 unsigned ShAmt) { 00458 if (!Subtarget->isLikeA9() && !Subtarget->isSwift()) 00459 return true; 00460 if (Shift.hasOneUse()) 00461 return true; 00462 // R << 2 is free. 00463 return ShOpcVal == ARM_AM::lsl && 00464 (ShAmt == 2 || (Subtarget->isSwift() && ShAmt == 1)); 00465 } 00466 00467 bool ARMDAGToDAGISel::SelectImmShifterOperand(SDValue N, 00468 SDValue &BaseReg, 00469 SDValue &Opc, 00470 bool CheckProfitability) { 00471 if (DisableShifterOp) 00472 return false; 00473 00474 ARM_AM::ShiftOpc ShOpcVal = ARM_AM::getShiftOpcForNode(N.getOpcode()); 00475 00476 // Don't match base register only case. That is matched to a separate 00477 // lower complexity pattern with explicit register operand. 00478 if (ShOpcVal == ARM_AM::no_shift) return false; 00479 00480 BaseReg = N.getOperand(0); 00481 unsigned ShImmVal = 0; 00482 ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N.getOperand(1)); 00483 if (!RHS) return false; 00484 ShImmVal = RHS->getZExtValue() & 31; 00485 Opc = CurDAG->getTargetConstant(ARM_AM::getSORegOpc(ShOpcVal, ShImmVal), 00486 MVT::i32); 00487 return true; 00488 } 00489 00490 bool ARMDAGToDAGISel::SelectRegShifterOperand(SDValue N, 00491 SDValue &BaseReg, 00492 SDValue &ShReg, 00493 SDValue &Opc, 00494 bool CheckProfitability) { 00495 if (DisableShifterOp) 00496 return false; 00497 00498 ARM_AM::ShiftOpc ShOpcVal = ARM_AM::getShiftOpcForNode(N.getOpcode()); 00499 00500 // Don't match base register only case. That is matched to a separate 00501 // lower complexity pattern with explicit register operand. 00502 if (ShOpcVal == ARM_AM::no_shift) return false; 00503 00504 BaseReg = N.getOperand(0); 00505 unsigned ShImmVal = 0; 00506 ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N.getOperand(1)); 00507 if (RHS) return false; 00508 00509 ShReg = N.getOperand(1); 00510 if (CheckProfitability && !isShifterOpProfitable(N, ShOpcVal, ShImmVal)) 00511 return false; 00512 Opc = CurDAG->getTargetConstant(ARM_AM::getSORegOpc(ShOpcVal, ShImmVal), 00513 MVT::i32); 00514 return true; 00515 } 00516 00517 00518 bool ARMDAGToDAGISel::SelectAddrModeImm12(SDValue N, 00519 SDValue &Base, 00520 SDValue &OffImm) { 00521 // Match simple R + imm12 operands. 00522 00523 // Base only. 00524 if (N.getOpcode() != ISD::ADD && N.getOpcode() != ISD::SUB && 00525 !CurDAG->isBaseWithConstantOffset(N)) { 00526 if (N.getOpcode() == ISD::FrameIndex) { 00527 // Match frame index. 00528 int FI = cast<FrameIndexSDNode>(N)->getIndex(); 00529 Base = CurDAG->getTargetFrameIndex(FI, 00530 getTargetLowering()->getPointerTy()); 00531 OffImm = CurDAG->getTargetConstant(0, MVT::i32); 00532 return true; 00533 } 00534 00535 if (N.getOpcode() == ARMISD::Wrapper && 00536 N.getOperand(0).getOpcode() != ISD::TargetGlobalAddress) { 00537 Base = N.getOperand(0); 00538 } else 00539 Base = N; 00540 OffImm = CurDAG->getTargetConstant(0, MVT::i32); 00541 return true; 00542 } 00543 00544 if (ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N.getOperand(1))) { 00545 int RHSC = (int)RHS->getSExtValue(); 00546 if (N.getOpcode() == ISD::SUB) 00547 RHSC = -RHSC; 00548 00549 if (RHSC > -0x1000 && RHSC < 0x1000) { // 12 bits 00550 Base = N.getOperand(0); 00551 if (Base.getOpcode() == ISD::FrameIndex) { 00552 int FI = cast<FrameIndexSDNode>(Base)->getIndex(); 00553 Base = CurDAG->getTargetFrameIndex(FI, 00554 getTargetLowering()->getPointerTy()); 00555 } 00556 OffImm = CurDAG->getTargetConstant(RHSC, MVT::i32); 00557 return true; 00558 } 00559 } 00560 00561 // Base only. 00562 Base = N; 00563 OffImm = CurDAG->getTargetConstant(0, MVT::i32); 00564 return true; 00565 } 00566 00567 00568 00569 bool ARMDAGToDAGISel::SelectLdStSOReg(SDValue N, SDValue &Base, SDValue &Offset, 00570 SDValue &Opc) { 00571 if (N.getOpcode() == ISD::MUL && 00572 ((!Subtarget->isLikeA9() && !Subtarget->isSwift()) || N.hasOneUse())) { 00573 if (ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N.getOperand(1))) { 00574 // X * [3,5,9] -> X + X * [2,4,8] etc. 00575 int RHSC = (int)RHS->getZExtValue(); 00576 if (RHSC & 1) { 00577 RHSC = RHSC & ~1; 00578 ARM_AM::AddrOpc AddSub = ARM_AM::add; 00579 if (RHSC < 0) { 00580 AddSub = ARM_AM::sub; 00581 RHSC = - RHSC; 00582 } 00583 if (isPowerOf2_32(RHSC)) { 00584 unsigned ShAmt = Log2_32(RHSC); 00585 Base = Offset = N.getOperand(0); 00586 Opc = CurDAG->getTargetConstant(ARM_AM::getAM2Opc(AddSub, ShAmt, 00587 ARM_AM::lsl), 00588 MVT::i32); 00589 return true; 00590 } 00591 } 00592 } 00593 } 00594 00595 if (N.getOpcode() != ISD::ADD && N.getOpcode() != ISD::SUB && 00596 // ISD::OR that is equivalent to an ISD::ADD. 00597 !CurDAG->isBaseWithConstantOffset(N)) 00598 return false; 00599 00600 // Leave simple R +/- imm12 operands for LDRi12 00601 if (N.getOpcode() == ISD::ADD || N.getOpcode() == ISD::OR) { 00602 int RHSC; 00603 if (isScaledConstantInRange(N.getOperand(1), /*Scale=*/1, 00604 -0x1000+1, 0x1000, RHSC)) // 12 bits. 00605 return false; 00606 } 00607 00608 // Otherwise this is R +/- [possibly shifted] R. 00609 ARM_AM::AddrOpc AddSub = N.getOpcode() == ISD::SUB ? ARM_AM::sub:ARM_AM::add; 00610 ARM_AM::ShiftOpc ShOpcVal = 00611 ARM_AM::getShiftOpcForNode(N.getOperand(1).getOpcode()); 00612 unsigned ShAmt = 0; 00613 00614 Base = N.getOperand(0); 00615 Offset = N.getOperand(1); 00616 00617 if (ShOpcVal != ARM_AM::no_shift) { 00618 // Check to see if the RHS of the shift is a constant, if not, we can't fold 00619 // it. 00620 if (ConstantSDNode *Sh = 00621 dyn_cast<ConstantSDNode>(N.getOperand(1).getOperand(1))) { 00622 ShAmt = Sh->getZExtValue(); 00623 if (isShifterOpProfitable(Offset, ShOpcVal, ShAmt)) 00624 Offset = N.getOperand(1).getOperand(0); 00625 else { 00626 ShAmt = 0; 00627 ShOpcVal = ARM_AM::no_shift; 00628 } 00629 } else { 00630 ShOpcVal = ARM_AM::no_shift; 00631 } 00632 } 00633 00634 // Try matching (R shl C) + (R). 00635 if (N.getOpcode() != ISD::SUB && ShOpcVal == ARM_AM::no_shift && 00636 !(Subtarget->isLikeA9() || Subtarget->isSwift() || 00637 N.getOperand(0).hasOneUse())) { 00638 ShOpcVal = ARM_AM::getShiftOpcForNode(N.getOperand(0).getOpcode()); 00639 if (ShOpcVal != ARM_AM::no_shift) { 00640 // Check to see if the RHS of the shift is a constant, if not, we can't 00641 // fold it. 00642 if (ConstantSDNode *Sh = 00643 dyn_cast<ConstantSDNode>(N.getOperand(0).getOperand(1))) { 00644 ShAmt = Sh->getZExtValue(); 00645 if (isShifterOpProfitable(N.getOperand(0), ShOpcVal, ShAmt)) { 00646 Offset = N.getOperand(0).getOperand(0); 00647 Base = N.getOperand(1); 00648 } else { 00649 ShAmt = 0; 00650 ShOpcVal = ARM_AM::no_shift; 00651 } 00652 } else { 00653 ShOpcVal = ARM_AM::no_shift; 00654 } 00655 } 00656 } 00657 00658 Opc = CurDAG->getTargetConstant(ARM_AM::getAM2Opc(AddSub, ShAmt, ShOpcVal), 00659 MVT::i32); 00660 return true; 00661 } 00662 00663 00664 //----- 00665 00666 AddrMode2Type ARMDAGToDAGISel::SelectAddrMode2Worker(SDValue N, 00667 SDValue &Base, 00668 SDValue &Offset, 00669 SDValue &Opc) { 00670 if (N.getOpcode() == ISD::MUL && 00671 (!(Subtarget->isLikeA9() || Subtarget->isSwift()) || N.hasOneUse())) { 00672 if (ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N.getOperand(1))) { 00673 // X * [3,5,9] -> X + X * [2,4,8] etc. 00674 int RHSC = (int)RHS->getZExtValue(); 00675 if (RHSC & 1) { 00676 RHSC = RHSC & ~1; 00677 ARM_AM::AddrOpc AddSub = ARM_AM::add; 00678 if (RHSC < 0) { 00679 AddSub = ARM_AM::sub; 00680 RHSC = - RHSC; 00681 } 00682 if (isPowerOf2_32(RHSC)) { 00683 unsigned ShAmt = Log2_32(RHSC); 00684 Base = Offset = N.getOperand(0); 00685 Opc = CurDAG->getTargetConstant(ARM_AM::getAM2Opc(AddSub, ShAmt, 00686 ARM_AM::lsl), 00687 MVT::i32); 00688 return AM2_SHOP; 00689 } 00690 } 00691 } 00692 } 00693 00694 if (N.getOpcode() != ISD::ADD && N.getOpcode() != ISD::SUB && 00695 // ISD::OR that is equivalent to an ADD. 00696 !CurDAG->isBaseWithConstantOffset(N)) { 00697 Base = N; 00698 if (N.getOpcode() == ISD::FrameIndex) { 00699 int FI = cast<FrameIndexSDNode>(N)->getIndex(); 00700 Base = CurDAG->getTargetFrameIndex(FI, 00701 getTargetLowering()->getPointerTy()); 00702 } else if (N.getOpcode() == ARMISD::Wrapper && 00703 N.getOperand(0).getOpcode() != ISD::TargetGlobalAddress) { 00704 Base = N.getOperand(0); 00705 } 00706 Offset = CurDAG->getRegister(0, MVT::i32); 00707 Opc = CurDAG->getTargetConstant(ARM_AM::getAM2Opc(ARM_AM::add, 0, 00708 ARM_AM::no_shift), 00709 MVT::i32); 00710 return AM2_BASE; 00711 } 00712 00713 // Match simple R +/- imm12 operands. 00714 if (N.getOpcode() != ISD::SUB) { 00715 int RHSC; 00716 if (isScaledConstantInRange(N.getOperand(1), /*Scale=*/1, 00717 -0x1000+1, 0x1000, RHSC)) { // 12 bits. 00718 Base = N.getOperand(0); 00719 if (Base.getOpcode() == ISD::FrameIndex) { 00720 int FI = cast<FrameIndexSDNode>(Base)->getIndex(); 00721 Base = CurDAG->getTargetFrameIndex(FI, 00722 getTargetLowering()->getPointerTy()); 00723 } 00724 Offset = CurDAG->getRegister(0, MVT::i32); 00725 00726 ARM_AM::AddrOpc AddSub = ARM_AM::add; 00727 if (RHSC < 0) { 00728 AddSub = ARM_AM::sub; 00729 RHSC = - RHSC; 00730 } 00731 Opc = CurDAG->getTargetConstant(ARM_AM::getAM2Opc(AddSub, RHSC, 00732 ARM_AM::no_shift), 00733 MVT::i32); 00734 return AM2_BASE; 00735 } 00736 } 00737 00738 if ((Subtarget->isLikeA9() || Subtarget->isSwift()) && !N.hasOneUse()) { 00739 // Compute R +/- (R << N) and reuse it. 00740 Base = N; 00741 Offset = CurDAG->getRegister(0, MVT::i32); 00742 Opc = CurDAG->getTargetConstant(ARM_AM::getAM2Opc(ARM_AM::add, 0, 00743 ARM_AM::no_shift), 00744 MVT::i32); 00745 return AM2_BASE; 00746 } 00747 00748 // Otherwise this is R +/- [possibly shifted] R. 00749 ARM_AM::AddrOpc AddSub = N.getOpcode() != ISD::SUB ? ARM_AM::add:ARM_AM::sub; 00750 ARM_AM::ShiftOpc ShOpcVal = 00751 ARM_AM::getShiftOpcForNode(N.getOperand(1).getOpcode()); 00752 unsigned ShAmt = 0; 00753 00754 Base = N.getOperand(0); 00755 Offset = N.getOperand(1); 00756 00757 if (ShOpcVal != ARM_AM::no_shift) { 00758 // Check to see if the RHS of the shift is a constant, if not, we can't fold 00759 // it. 00760 if (ConstantSDNode *Sh = 00761 dyn_cast<ConstantSDNode>(N.getOperand(1).getOperand(1))) { 00762 ShAmt = Sh->getZExtValue(); 00763 if (isShifterOpProfitable(Offset, ShOpcVal, ShAmt)) 00764 Offset = N.getOperand(1).getOperand(0); 00765 else { 00766 ShAmt = 0; 00767 ShOpcVal = ARM_AM::no_shift; 00768 } 00769 } else { 00770 ShOpcVal = ARM_AM::no_shift; 00771 } 00772 } 00773 00774 // Try matching (R shl C) + (R). 00775 if (N.getOpcode() != ISD::SUB && ShOpcVal == ARM_AM::no_shift && 00776 !(Subtarget->isLikeA9() || Subtarget->isSwift() || 00777 N.getOperand(0).hasOneUse())) { 00778 ShOpcVal = ARM_AM::getShiftOpcForNode(N.getOperand(0).getOpcode()); 00779 if (ShOpcVal != ARM_AM::no_shift) { 00780 // Check to see if the RHS of the shift is a constant, if not, we can't 00781 // fold it. 00782 if (ConstantSDNode *Sh = 00783 dyn_cast<ConstantSDNode>(N.getOperand(0).getOperand(1))) { 00784 ShAmt = Sh->getZExtValue(); 00785 if (isShifterOpProfitable(N.getOperand(0), ShOpcVal, ShAmt)) { 00786 Offset = N.getOperand(0).getOperand(0); 00787 Base = N.getOperand(1); 00788 } else { 00789 ShAmt = 0; 00790 ShOpcVal = ARM_AM::no_shift; 00791 } 00792 } else { 00793 ShOpcVal = ARM_AM::no_shift; 00794 } 00795 } 00796 } 00797 00798 Opc = CurDAG->getTargetConstant(ARM_AM::getAM2Opc(AddSub, ShAmt, ShOpcVal), 00799 MVT::i32); 00800 return AM2_SHOP; 00801 } 00802 00803 bool ARMDAGToDAGISel::SelectAddrMode2OffsetReg(SDNode *Op, SDValue N, 00804 SDValue &Offset, SDValue &Opc) { 00805 unsigned Opcode = Op->getOpcode(); 00806 ISD::MemIndexedMode AM = (Opcode == ISD::LOAD) 00807 ? cast<LoadSDNode>(Op)->getAddressingMode() 00808 : cast<StoreSDNode>(Op)->getAddressingMode(); 00809 ARM_AM::AddrOpc AddSub = (AM == ISD::PRE_INC || AM == ISD::POST_INC) 00810 ? ARM_AM::add : ARM_AM::sub; 00811 int Val; 00812 if (isScaledConstantInRange(N, /*Scale=*/1, 0, 0x1000, Val)) 00813 return false; 00814 00815 Offset = N; 00816 ARM_AM::ShiftOpc ShOpcVal = ARM_AM::getShiftOpcForNode(N.getOpcode()); 00817 unsigned ShAmt = 0; 00818 if (ShOpcVal != ARM_AM::no_shift) { 00819 // Check to see if the RHS of the shift is a constant, if not, we can't fold 00820 // it. 00821 if (ConstantSDNode *Sh = dyn_cast<ConstantSDNode>(N.getOperand(1))) { 00822 ShAmt = Sh->getZExtValue(); 00823 if (isShifterOpProfitable(N, ShOpcVal, ShAmt)) 00824 Offset = N.getOperand(0); 00825 else { 00826 ShAmt = 0; 00827 ShOpcVal = ARM_AM::no_shift; 00828 } 00829 } else { 00830 ShOpcVal = ARM_AM::no_shift; 00831 } 00832 } 00833 00834 Opc = CurDAG->getTargetConstant(ARM_AM::getAM2Opc(AddSub, ShAmt, ShOpcVal), 00835 MVT::i32); 00836 return true; 00837 } 00838 00839 bool ARMDAGToDAGISel::SelectAddrMode2OffsetImmPre(SDNode *Op, SDValue N, 00840 SDValue &Offset, SDValue &Opc) { 00841 unsigned Opcode = Op->getOpcode(); 00842 ISD::MemIndexedMode AM = (Opcode == ISD::LOAD) 00843 ? cast<LoadSDNode>(Op)->getAddressingMode() 00844 : cast<StoreSDNode>(Op)->getAddressingMode(); 00845 ARM_AM::AddrOpc AddSub = (AM == ISD::PRE_INC || AM == ISD::POST_INC) 00846 ? ARM_AM::add : ARM_AM::sub; 00847 int Val; 00848 if (isScaledConstantInRange(N, /*Scale=*/1, 0, 0x1000, Val)) { // 12 bits. 00849 if (AddSub == ARM_AM::sub) Val *= -1; 00850 Offset = CurDAG->getRegister(0, MVT::i32); 00851 Opc = CurDAG->getTargetConstant(Val, MVT::i32); 00852 return true; 00853 } 00854 00855 return false; 00856 } 00857 00858 00859 bool ARMDAGToDAGISel::SelectAddrMode2OffsetImm(SDNode *Op, SDValue N, 00860 SDValue &Offset, SDValue &Opc) { 00861 unsigned Opcode = Op->getOpcode(); 00862 ISD::MemIndexedMode AM = (Opcode == ISD::LOAD) 00863 ? cast<LoadSDNode>(Op)->getAddressingMode() 00864 : cast<StoreSDNode>(Op)->getAddressingMode(); 00865 ARM_AM::AddrOpc AddSub = (AM == ISD::PRE_INC || AM == ISD::POST_INC) 00866 ? ARM_AM::add : ARM_AM::sub; 00867 int Val; 00868 if (isScaledConstantInRange(N, /*Scale=*/1, 0, 0x1000, Val)) { // 12 bits. 00869 Offset = CurDAG->getRegister(0, MVT::i32); 00870 Opc = CurDAG->getTargetConstant(ARM_AM::getAM2Opc(AddSub, Val, 00871 ARM_AM::no_shift), 00872 MVT::i32); 00873 return true; 00874 } 00875 00876 return false; 00877 } 00878 00879 bool ARMDAGToDAGISel::SelectAddrOffsetNone(SDValue N, SDValue &Base) { 00880 Base = N; 00881 return true; 00882 } 00883 00884 bool ARMDAGToDAGISel::SelectAddrMode3(SDValue N, 00885 SDValue &Base, SDValue &Offset, 00886 SDValue &Opc) { 00887 if (N.getOpcode() == ISD::SUB) { 00888 // X - C is canonicalize to X + -C, no need to handle it here. 00889 Base = N.getOperand(0); 00890 Offset = N.getOperand(1); 00891 Opc = CurDAG->getTargetConstant(ARM_AM::getAM3Opc(ARM_AM::sub, 0),MVT::i32); 00892 return true; 00893 } 00894 00895 if (!CurDAG->isBaseWithConstantOffset(N)) { 00896 Base = N; 00897 if (N.getOpcode() == ISD::FrameIndex) { 00898 int FI = cast<FrameIndexSDNode>(N)->getIndex(); 00899 Base = CurDAG->getTargetFrameIndex(FI, 00900 getTargetLowering()->getPointerTy()); 00901 } 00902 Offset = CurDAG->getRegister(0, MVT::i32); 00903 Opc = CurDAG->getTargetConstant(ARM_AM::getAM3Opc(ARM_AM::add, 0),MVT::i32); 00904 return true; 00905 } 00906 00907 // If the RHS is +/- imm8, fold into addr mode. 00908 int RHSC; 00909 if (isScaledConstantInRange(N.getOperand(1), /*Scale=*/1, 00910 -256 + 1, 256, RHSC)) { // 8 bits. 00911 Base = N.getOperand(0); 00912 if (Base.getOpcode() == ISD::FrameIndex) { 00913 int FI = cast<FrameIndexSDNode>(Base)->getIndex(); 00914 Base = CurDAG->getTargetFrameIndex(FI, 00915 getTargetLowering()->getPointerTy()); 00916 } 00917 Offset = CurDAG->getRegister(0, MVT::i32); 00918 00919 ARM_AM::AddrOpc AddSub = ARM_AM::add; 00920 if (RHSC < 0) { 00921 AddSub = ARM_AM::sub; 00922 RHSC = -RHSC; 00923 } 00924 Opc = CurDAG->getTargetConstant(ARM_AM::getAM3Opc(AddSub, RHSC),MVT::i32); 00925 return true; 00926 } 00927 00928 Base = N.getOperand(0); 00929 Offset = N.getOperand(1); 00930 Opc = CurDAG->getTargetConstant(ARM_AM::getAM3Opc(ARM_AM::add, 0), MVT::i32); 00931 return true; 00932 } 00933 00934 bool ARMDAGToDAGISel::SelectAddrMode3Offset(SDNode *Op, SDValue N, 00935 SDValue &Offset, SDValue &Opc) { 00936 unsigned Opcode = Op->getOpcode(); 00937 ISD::MemIndexedMode AM = (Opcode == ISD::LOAD) 00938 ? cast<LoadSDNode>(Op)->getAddressingMode() 00939 : cast<StoreSDNode>(Op)->getAddressingMode(); 00940 ARM_AM::AddrOpc AddSub = (AM == ISD::PRE_INC || AM == ISD::POST_INC) 00941 ? ARM_AM::add : ARM_AM::sub; 00942 int Val; 00943 if (isScaledConstantInRange(N, /*Scale=*/1, 0, 256, Val)) { // 12 bits. 00944 Offset = CurDAG->getRegister(0, MVT::i32); 00945 Opc = CurDAG->getTargetConstant(ARM_AM::getAM3Opc(AddSub, Val), MVT::i32); 00946 return true; 00947 } 00948 00949 Offset = N; 00950 Opc = CurDAG->getTargetConstant(ARM_AM::getAM3Opc(AddSub, 0), MVT::i32); 00951 return true; 00952 } 00953 00954 bool ARMDAGToDAGISel::SelectAddrMode5(SDValue N, 00955 SDValue &Base, SDValue &Offset) { 00956 if (!CurDAG->isBaseWithConstantOffset(N)) { 00957 Base = N; 00958 if (N.getOpcode() == ISD::FrameIndex) { 00959 int FI = cast<FrameIndexSDNode>(N)->getIndex(); 00960 Base = CurDAG->getTargetFrameIndex(FI, 00961 getTargetLowering()->getPointerTy()); 00962 } else if (N.getOpcode() == ARMISD::Wrapper && 00963 N.getOperand(0).getOpcode() != ISD::TargetGlobalAddress) { 00964 Base = N.getOperand(0); 00965 } 00966 Offset = CurDAG->getTargetConstant(ARM_AM::getAM5Opc(ARM_AM::add, 0), 00967 MVT::i32); 00968 return true; 00969 } 00970 00971 // If the RHS is +/- imm8, fold into addr mode. 00972 int RHSC; 00973 if (isScaledConstantInRange(N.getOperand(1), /*Scale=*/4, 00974 -256 + 1, 256, RHSC)) { 00975 Base = N.getOperand(0); 00976 if (Base.getOpcode() == ISD::FrameIndex) { 00977 int FI = cast<FrameIndexSDNode>(Base)->getIndex(); 00978 Base = CurDAG->getTargetFrameIndex(FI, 00979 getTargetLowering()->getPointerTy()); 00980 } 00981 00982 ARM_AM::AddrOpc AddSub = ARM_AM::add; 00983 if (RHSC < 0) { 00984 AddSub = ARM_AM::sub; 00985 RHSC = -RHSC; 00986 } 00987 Offset = CurDAG->getTargetConstant(ARM_AM::getAM5Opc(AddSub, RHSC), 00988 MVT::i32); 00989 return true; 00990 } 00991 00992 Base = N; 00993 Offset = CurDAG->getTargetConstant(ARM_AM::getAM5Opc(ARM_AM::add, 0), 00994 MVT::i32); 00995 return true; 00996 } 00997 00998 bool ARMDAGToDAGISel::SelectAddrMode6(SDNode *Parent, SDValue N, SDValue &Addr, 00999 SDValue &Align) { 01000 Addr = N; 01001 01002 unsigned Alignment = 0; 01003 if (LSBaseSDNode *LSN = dyn_cast<LSBaseSDNode>(Parent)) { 01004 // This case occurs only for VLD1-lane/dup and VST1-lane instructions. 01005 // The maximum alignment is equal to the memory size being referenced. 01006 unsigned LSNAlign = LSN->getAlignment(); 01007 unsigned MemSize = LSN->getMemoryVT().getSizeInBits() / 8; 01008 if (LSNAlign >= MemSize && MemSize > 1) 01009 Alignment = MemSize; 01010 } else { 01011 // All other uses of addrmode6 are for intrinsics. For now just record 01012 // the raw alignment value; it will be refined later based on the legal 01013 // alignment operands for the intrinsic. 01014 Alignment = cast<MemIntrinsicSDNode>(Parent)->getAlignment(); 01015 } 01016 01017 Align = CurDAG->getTargetConstant(Alignment, MVT::i32); 01018 return true; 01019 } 01020 01021 bool ARMDAGToDAGISel::SelectAddrMode6Offset(SDNode *Op, SDValue N, 01022 SDValue &Offset) { 01023 LSBaseSDNode *LdSt = cast<LSBaseSDNode>(Op); 01024 ISD::MemIndexedMode AM = LdSt->getAddressingMode(); 01025 if (AM != ISD::POST_INC) 01026 return false; 01027 Offset = N; 01028 if (ConstantSDNode *NC = dyn_cast<ConstantSDNode>(N)) { 01029 if (NC->getZExtValue() * 8 == LdSt->getMemoryVT().getSizeInBits()) 01030 Offset = CurDAG->getRegister(0, MVT::i32); 01031 } 01032 return true; 01033 } 01034 01035 bool ARMDAGToDAGISel::SelectAddrModePC(SDValue N, 01036 SDValue &Offset, SDValue &Label) { 01037 if (N.getOpcode() == ARMISD::PIC_ADD && N.hasOneUse()) { 01038 Offset = N.getOperand(0); 01039 SDValue N1 = N.getOperand(1); 01040 Label = CurDAG->getTargetConstant(cast<ConstantSDNode>(N1)->getZExtValue(), 01041 MVT::i32); 01042 return true; 01043 } 01044 01045 return false; 01046 } 01047 01048 01049 //===----------------------------------------------------------------------===// 01050 // Thumb Addressing Modes 01051 //===----------------------------------------------------------------------===// 01052 01053 bool ARMDAGToDAGISel::SelectThumbAddrModeRR(SDValue N, 01054 SDValue &Base, SDValue &Offset){ 01055 if (N.getOpcode() != ISD::ADD && !CurDAG->isBaseWithConstantOffset(N)) { 01056 ConstantSDNode *NC = dyn_cast<ConstantSDNode>(N); 01057 if (!NC || !NC->isNullValue()) 01058 return false; 01059 01060 Base = Offset = N; 01061 return true; 01062 } 01063 01064 Base = N.getOperand(0); 01065 Offset = N.getOperand(1); 01066 return true; 01067 } 01068 01069 bool 01070 ARMDAGToDAGISel::SelectThumbAddrModeRI(SDValue N, SDValue &Base, 01071 SDValue &Offset, unsigned Scale) { 01072 if (Scale == 4) { 01073 SDValue TmpBase, TmpOffImm; 01074 if (SelectThumbAddrModeSP(N, TmpBase, TmpOffImm)) 01075 return false; // We want to select tLDRspi / tSTRspi instead. 01076 01077 if (N.getOpcode() == ARMISD::Wrapper && 01078 N.getOperand(0).getOpcode() == ISD::TargetConstantPool) 01079 return false; // We want to select tLDRpci instead. 01080 } 01081 01082 if (!CurDAG->isBaseWithConstantOffset(N)) 01083 return false; 01084 01085 // Thumb does not have [sp, r] address mode. 01086 RegisterSDNode *LHSR = dyn_cast<RegisterSDNode>(N.getOperand(0)); 01087 RegisterSDNode *RHSR = dyn_cast<RegisterSDNode>(N.getOperand(1)); 01088 if ((LHSR && LHSR->getReg() == ARM::SP) || 01089 (RHSR && RHSR->getReg() == ARM::SP)) 01090 return false; 01091 01092 // FIXME: Why do we explicitly check for a match here and then return false? 01093 // Presumably to allow something else to match, but shouldn't this be 01094 // documented? 01095 int RHSC; 01096 if (isScaledConstantInRange(N.getOperand(1), Scale, 0, 32, RHSC)) 01097 return false; 01098 01099 Base = N.getOperand(0); 01100 Offset = N.getOperand(1); 01101 return true; 01102 } 01103 01104 bool 01105 ARMDAGToDAGISel::SelectThumbAddrModeRI5S1(SDValue N, 01106 SDValue &Base, 01107 SDValue &Offset) { 01108 return SelectThumbAddrModeRI(N, Base, Offset, 1); 01109 } 01110 01111 bool 01112 ARMDAGToDAGISel::SelectThumbAddrModeRI5S2(SDValue N, 01113 SDValue &Base, 01114 SDValue &Offset) { 01115 return SelectThumbAddrModeRI(N, Base, Offset, 2); 01116 } 01117 01118 bool 01119 ARMDAGToDAGISel::SelectThumbAddrModeRI5S4(SDValue N, 01120 SDValue &Base, 01121 SDValue &Offset) { 01122 return SelectThumbAddrModeRI(N, Base, Offset, 4); 01123 } 01124 01125 bool 01126 ARMDAGToDAGISel::SelectThumbAddrModeImm5S(SDValue N, unsigned Scale, 01127 SDValue &Base, SDValue &OffImm) { 01128 if (Scale == 4) { 01129 SDValue TmpBase, TmpOffImm; 01130 if (SelectThumbAddrModeSP(N, TmpBase, TmpOffImm)) 01131 return false; // We want to select tLDRspi / tSTRspi instead. 01132 01133 if (N.getOpcode() == ARMISD::Wrapper && 01134 N.getOperand(0).getOpcode() == ISD::TargetConstantPool) 01135 return false; // We want to select tLDRpci instead. 01136 } 01137 01138 if (!CurDAG->isBaseWithConstantOffset(N)) { 01139 if (N.getOpcode() == ARMISD::Wrapper && 01140 N.getOperand(0).getOpcode() != ISD::TargetGlobalAddress) { 01141 Base = N.getOperand(0); 01142 } else { 01143 Base = N; 01144 } 01145 01146 OffImm = CurDAG->getTargetConstant(0, MVT::i32); 01147 return true; 01148 } 01149 01150 RegisterSDNode *LHSR = dyn_cast<RegisterSDNode>(N.getOperand(0)); 01151 RegisterSDNode *RHSR = dyn_cast<RegisterSDNode>(N.getOperand(1)); 01152 if ((LHSR && LHSR->getReg() == ARM::SP) || 01153 (RHSR && RHSR->getReg() == ARM::SP)) { 01154 ConstantSDNode *LHS = dyn_cast<ConstantSDNode>(N.getOperand(0)); 01155 ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N.getOperand(1)); 01156 unsigned LHSC = LHS ? LHS->getZExtValue() : 0; 01157 unsigned RHSC = RHS ? RHS->getZExtValue() : 0; 01158 01159 // Thumb does not have [sp, #imm5] address mode for non-zero imm5. 01160 if (LHSC != 0 || RHSC != 0) return false; 01161 01162 Base = N; 01163 OffImm = CurDAG->getTargetConstant(0, MVT::i32); 01164 return true; 01165 } 01166 01167 // If the RHS is + imm5 * scale, fold into addr mode. 01168 int RHSC; 01169 if (isScaledConstantInRange(N.getOperand(1), Scale, 0, 32, RHSC)) { 01170 Base = N.getOperand(0); 01171 OffImm = CurDAG->getTargetConstant(RHSC, MVT::i32); 01172 return true; 01173 } 01174 01175 Base = N.getOperand(0); 01176 OffImm = CurDAG->getTargetConstant(0, MVT::i32); 01177 return true; 01178 } 01179 01180 bool 01181 ARMDAGToDAGISel::SelectThumbAddrModeImm5S4(SDValue N, SDValue &Base, 01182 SDValue &OffImm) { 01183 return SelectThumbAddrModeImm5S(N, 4, Base, OffImm); 01184 } 01185 01186 bool 01187 ARMDAGToDAGISel::SelectThumbAddrModeImm5S2(SDValue N, SDValue &Base, 01188 SDValue &OffImm) { 01189 return SelectThumbAddrModeImm5S(N, 2, Base, OffImm); 01190 } 01191 01192 bool 01193 ARMDAGToDAGISel::SelectThumbAddrModeImm5S1(SDValue N, SDValue &Base, 01194 SDValue &OffImm) { 01195 return SelectThumbAddrModeImm5S(N, 1, Base, OffImm); 01196 } 01197 01198 bool ARMDAGToDAGISel::SelectThumbAddrModeSP(SDValue N, 01199 SDValue &Base, SDValue &OffImm) { 01200 if (N.getOpcode() == ISD::FrameIndex) { 01201 int FI = cast<FrameIndexSDNode>(N)->getIndex(); 01202 Base = CurDAG->getTargetFrameIndex(FI, 01203 getTargetLowering()->getPointerTy()); 01204 OffImm = CurDAG->getTargetConstant(0, MVT::i32); 01205 return true; 01206 } 01207 01208 if (!CurDAG->isBaseWithConstantOffset(N)) 01209 return false; 01210 01211 RegisterSDNode *LHSR = dyn_cast<RegisterSDNode>(N.getOperand(0)); 01212 if (N.getOperand(0).getOpcode() == ISD::FrameIndex || 01213 (LHSR && LHSR->getReg() == ARM::SP)) { 01214 // If the RHS is + imm8 * scale, fold into addr mode. 01215 int RHSC; 01216 if (isScaledConstantInRange(N.getOperand(1), /*Scale=*/4, 0, 256, RHSC)) { 01217 Base = N.getOperand(0); 01218 if (Base.getOpcode() == ISD::FrameIndex) { 01219 int FI = cast<FrameIndexSDNode>(Base)->getIndex(); 01220 Base = CurDAG->getTargetFrameIndex(FI, 01221 getTargetLowering()->getPointerTy()); 01222 } 01223 OffImm = CurDAG->getTargetConstant(RHSC, MVT::i32); 01224 return true; 01225 } 01226 } 01227 01228 return false; 01229 } 01230 01231 01232 //===----------------------------------------------------------------------===// 01233 // Thumb 2 Addressing Modes 01234 //===----------------------------------------------------------------------===// 01235 01236 01237 bool ARMDAGToDAGISel::SelectT2ShifterOperandReg(SDValue N, SDValue &BaseReg, 01238 SDValue &Opc) { 01239 if (DisableShifterOp) 01240 return false; 01241 01242 ARM_AM::ShiftOpc ShOpcVal = ARM_AM::getShiftOpcForNode(N.getOpcode()); 01243 01244 // Don't match base register only case. That is matched to a separate 01245 // lower complexity pattern with explicit register operand. 01246 if (ShOpcVal == ARM_AM::no_shift) return false; 01247 01248 BaseReg = N.getOperand(0); 01249 unsigned ShImmVal = 0; 01250 if (ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N.getOperand(1))) { 01251 ShImmVal = RHS->getZExtValue() & 31; 01252 Opc = getI32Imm(ARM_AM::getSORegOpc(ShOpcVal, ShImmVal)); 01253 return true; 01254 } 01255 01256 return false; 01257 } 01258 01259 bool ARMDAGToDAGISel::SelectT2AddrModeImm12(SDValue N, 01260 SDValue &Base, SDValue &OffImm) { 01261 // Match simple R + imm12 operands. 01262 01263 // Base only. 01264 if (N.getOpcode() != ISD::ADD && N.getOpcode() != ISD::SUB && 01265 !CurDAG->isBaseWithConstantOffset(N)) { 01266 if (N.getOpcode() == ISD::FrameIndex) { 01267 // Match frame index. 01268 int FI = cast<FrameIndexSDNode>(N)->getIndex(); 01269 Base = CurDAG->getTargetFrameIndex(FI, 01270 getTargetLowering()->getPointerTy()); 01271 OffImm = CurDAG->getTargetConstant(0, MVT::i32); 01272 return true; 01273 } 01274 01275 if (N.getOpcode() == ARMISD::Wrapper && 01276 N.getOperand(0).getOpcode() != ISD::TargetGlobalAddress) { 01277 Base = N.getOperand(0); 01278 if (Base.getOpcode() == ISD::TargetConstantPool) 01279 return false; // We want to select t2LDRpci instead. 01280 } else 01281 Base = N; 01282 OffImm = CurDAG->getTargetConstant(0, MVT::i32); 01283 return true; 01284 } 01285 01286 if (ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N.getOperand(1))) { 01287 if (SelectT2AddrModeImm8(N, Base, OffImm)) 01288 // Let t2LDRi8 handle (R - imm8). 01289 return false; 01290 01291 int RHSC = (int)RHS->getZExtValue(); 01292 if (N.getOpcode() == ISD::SUB) 01293 RHSC = -RHSC; 01294 01295 if (RHSC >= 0 && RHSC < 0x1000) { // 12 bits (unsigned) 01296 Base = N.getOperand(0); 01297 if (Base.getOpcode() == ISD::FrameIndex) { 01298 int FI = cast<FrameIndexSDNode>(Base)->getIndex(); 01299 Base = CurDAG->getTargetFrameIndex(FI, 01300 getTargetLowering()->getPointerTy()); 01301 } 01302 OffImm = CurDAG->getTargetConstant(RHSC, MVT::i32); 01303 return true; 01304 } 01305 } 01306 01307 // Base only. 01308 Base = N; 01309 OffImm = CurDAG->getTargetConstant(0, MVT::i32); 01310 return true; 01311 } 01312 01313 bool ARMDAGToDAGISel::SelectT2AddrModeImm8(SDValue N, 01314 SDValue &Base, SDValue &OffImm) { 01315 // Match simple R - imm8 operands. 01316 if (N.getOpcode() != ISD::ADD && N.getOpcode() != ISD::SUB && 01317 !CurDAG->isBaseWithConstantOffset(N)) 01318 return false; 01319 01320 if (ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N.getOperand(1))) { 01321 int RHSC = (int)RHS->getSExtValue(); 01322 if (N.getOpcode() == ISD::SUB) 01323 RHSC = -RHSC; 01324 01325 if ((RHSC >= -255) && (RHSC < 0)) { // 8 bits (always negative) 01326 Base = N.getOperand(0); 01327 if (Base.getOpcode() == ISD::FrameIndex) { 01328 int FI = cast<FrameIndexSDNode>(Base)->getIndex(); 01329 Base = CurDAG->getTargetFrameIndex(FI, 01330 getTargetLowering()->getPointerTy()); 01331 } 01332 OffImm = CurDAG->getTargetConstant(RHSC, MVT::i32); 01333 return true; 01334 } 01335 } 01336 01337 return false; 01338 } 01339 01340 bool ARMDAGToDAGISel::SelectT2AddrModeImm8Offset(SDNode *Op, SDValue N, 01341 SDValue &OffImm){ 01342 unsigned Opcode = Op->getOpcode(); 01343 ISD::MemIndexedMode AM = (Opcode == ISD::LOAD) 01344 ? cast<LoadSDNode>(Op)->getAddressingMode() 01345 : cast<StoreSDNode>(Op)->getAddressingMode(); 01346 int RHSC; 01347 if (isScaledConstantInRange(N, /*Scale=*/1, 0, 0x100, RHSC)) { // 8 bits. 01348 OffImm = ((AM == ISD::PRE_INC) || (AM == ISD::POST_INC)) 01349 ? CurDAG->getTargetConstant(RHSC, MVT::i32) 01350 : CurDAG->getTargetConstant(-RHSC, MVT::i32); 01351 return true; 01352 } 01353 01354 return false; 01355 } 01356 01357 bool ARMDAGToDAGISel::SelectT2AddrModeSoReg(SDValue N, 01358 SDValue &Base, 01359 SDValue &OffReg, SDValue &ShImm) { 01360 // (R - imm8) should be handled by t2LDRi8. The rest are handled by t2LDRi12. 01361 if (N.getOpcode() != ISD::ADD && !CurDAG->isBaseWithConstantOffset(N)) 01362 return false; 01363 01364 // Leave (R + imm12) for t2LDRi12, (R - imm8) for t2LDRi8. 01365 if (ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N.getOperand(1))) { 01366 int RHSC = (int)RHS->getZExtValue(); 01367 if (RHSC >= 0 && RHSC < 0x1000) // 12 bits (unsigned) 01368 return false; 01369 else if (RHSC < 0 && RHSC >= -255) // 8 bits 01370 return false; 01371 } 01372 01373 // Look for (R + R) or (R + (R << [1,2,3])). 01374 unsigned ShAmt = 0; 01375 Base = N.getOperand(0); 01376 OffReg = N.getOperand(1); 01377 01378 // Swap if it is ((R << c) + R). 01379 ARM_AM::ShiftOpc ShOpcVal = ARM_AM::getShiftOpcForNode(OffReg.getOpcode()); 01380 if (ShOpcVal != ARM_AM::lsl) { 01381 ShOpcVal = ARM_AM::getShiftOpcForNode(Base.getOpcode()); 01382 if (ShOpcVal == ARM_AM::lsl) 01383 std::swap(Base, OffReg); 01384 } 01385 01386 if (ShOpcVal == ARM_AM::lsl) { 01387 // Check to see if the RHS of the shift is a constant, if not, we can't fold 01388 // it. 01389 if (ConstantSDNode *Sh = dyn_cast<ConstantSDNode>(OffReg.getOperand(1))) { 01390 ShAmt = Sh->getZExtValue(); 01391 if (ShAmt < 4 && isShifterOpProfitable(OffReg, ShOpcVal, ShAmt)) 01392 OffReg = OffReg.getOperand(0); 01393 else { 01394 ShAmt = 0; 01395 ShOpcVal = ARM_AM::no_shift; 01396 } 01397 } else { 01398 ShOpcVal = ARM_AM::no_shift; 01399 } 01400 } 01401 01402 ShImm = CurDAG->getTargetConstant(ShAmt, MVT::i32); 01403 01404 return true; 01405 } 01406 01407 bool ARMDAGToDAGISel::SelectT2AddrModeExclusive(SDValue N, SDValue &Base, 01408 SDValue &OffImm) { 01409 // This *must* succeed since it's used for the irreplaceable ldrex and strex 01410 // instructions. 01411 Base = N; 01412 OffImm = CurDAG->getTargetConstant(0, MVT::i32); 01413 01414 if (N.getOpcode() != ISD::ADD || !CurDAG->isBaseWithConstantOffset(N)) 01415 return true; 01416 01417 ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N.getOperand(1)); 01418 if (!RHS) 01419 return true; 01420 01421 uint32_t RHSC = (int)RHS->getZExtValue(); 01422 if (RHSC > 1020 || RHSC % 4 != 0) 01423 return true; 01424 01425 Base = N.getOperand(0); 01426 if (Base.getOpcode() == ISD::FrameIndex) { 01427 int FI = cast<FrameIndexSDNode>(Base)->getIndex(); 01428 Base = CurDAG->getTargetFrameIndex(FI, getTargetLowering()->getPointerTy()); 01429 } 01430 01431 OffImm = CurDAG->getTargetConstant(RHSC / 4, MVT::i32); 01432 return true; 01433 } 01434 01435 //===--------------------------------------------------------------------===// 01436 01437 /// getAL - Returns a ARMCC::AL immediate node. 01438 static inline SDValue getAL(SelectionDAG *CurDAG) { 01439 return CurDAG->getTargetConstant((uint64_t)ARMCC::AL, MVT::i32); 01440 } 01441 01442 SDNode *ARMDAGToDAGISel::SelectARMIndexedLoad(SDNode *N) { 01443 LoadSDNode *LD = cast<LoadSDNode>(N); 01444 ISD::MemIndexedMode AM = LD->getAddressingMode(); 01445 if (AM == ISD::UNINDEXED) 01446 return nullptr; 01447 01448 EVT LoadedVT = LD->getMemoryVT(); 01449 SDValue Offset, AMOpc; 01450 bool isPre = (AM == ISD::PRE_INC) || (AM == ISD::PRE_DEC); 01451 unsigned Opcode = 0; 01452 bool Match = false; 01453 if (LoadedVT == MVT::i32 && isPre && 01454 SelectAddrMode2OffsetImmPre(N, LD->getOffset(), Offset, AMOpc)) { 01455 Opcode = ARM::LDR_PRE_IMM; 01456 Match = true; 01457 } else if (LoadedVT == MVT::i32 && !isPre && 01458 SelectAddrMode2OffsetImm(N, LD->getOffset(), Offset, AMOpc)) { 01459 Opcode = ARM::LDR_POST_IMM; 01460 Match = true; 01461 } else if (LoadedVT == MVT::i32 && 01462 SelectAddrMode2OffsetReg(N, LD->getOffset(), Offset, AMOpc)) { 01463 Opcode = isPre ? ARM::LDR_PRE_REG : ARM::LDR_POST_REG; 01464 Match = true; 01465 01466 } else if (LoadedVT == MVT::i16 && 01467 SelectAddrMode3Offset(N, LD->getOffset(), Offset, AMOpc)) { 01468 Match = true; 01469 Opcode = (LD->getExtensionType() == ISD::SEXTLOAD) 01470 ? (isPre ? ARM::LDRSH_PRE : ARM::LDRSH_POST) 01471 : (isPre ? ARM::LDRH_PRE : ARM::LDRH_POST); 01472 } else if (LoadedVT == MVT::i8 || LoadedVT == MVT::i1) { 01473 if (LD->getExtensionType() == ISD::SEXTLOAD) { 01474 if (SelectAddrMode3Offset(N, LD->getOffset(), Offset, AMOpc)) { 01475 Match = true; 01476 Opcode = isPre ? ARM::LDRSB_PRE : ARM::LDRSB_POST; 01477 } 01478 } else { 01479 if (isPre && 01480 SelectAddrMode2OffsetImmPre(N, LD->getOffset(), Offset, AMOpc)) { 01481 Match = true; 01482 Opcode = ARM::LDRB_PRE_IMM; 01483 } else if (!isPre && 01484 SelectAddrMode2OffsetImm(N, LD->getOffset(), Offset, AMOpc)) { 01485 Match = true; 01486 Opcode = ARM::LDRB_POST_IMM; 01487 } else if (SelectAddrMode2OffsetReg(N, LD->getOffset(), Offset, AMOpc)) { 01488 Match = true; 01489 Opcode = isPre ? ARM::LDRB_PRE_REG : ARM::LDRB_POST_REG; 01490 } 01491 } 01492 } 01493 01494 if (Match) { 01495 if (Opcode == ARM::LDR_PRE_IMM || Opcode == ARM::LDRB_PRE_IMM) { 01496 SDValue Chain = LD->getChain(); 01497 SDValue Base = LD->getBasePtr(); 01498 SDValue Ops[]= { Base, AMOpc, getAL(CurDAG), 01499 CurDAG->getRegister(0, MVT::i32), Chain }; 01500 return CurDAG->getMachineNode(Opcode, SDLoc(N), MVT::i32, 01501 MVT::i32, MVT::Other, Ops); 01502 } else { 01503 SDValue Chain = LD->getChain(); 01504 SDValue Base = LD->getBasePtr(); 01505 SDValue Ops[]= { Base, Offset, AMOpc, getAL(CurDAG), 01506 CurDAG->getRegister(0, MVT::i32), Chain }; 01507 return CurDAG->getMachineNode(Opcode, SDLoc(N), MVT::i32, 01508 MVT::i32, MVT::Other, Ops); 01509 } 01510 } 01511 01512 return nullptr; 01513 } 01514 01515 SDNode *ARMDAGToDAGISel::SelectT2IndexedLoad(SDNode *N) { 01516 LoadSDNode *LD = cast<LoadSDNode>(N); 01517 ISD::MemIndexedMode AM = LD->getAddressingMode(); 01518 if (AM == ISD::UNINDEXED) 01519 return nullptr; 01520 01521 EVT LoadedVT = LD->getMemoryVT(); 01522 bool isSExtLd = LD->getExtensionType() == ISD::SEXTLOAD; 01523 SDValue Offset; 01524 bool isPre = (AM == ISD::PRE_INC) || (AM == ISD::PRE_DEC); 01525 unsigned Opcode = 0; 01526 bool Match = false; 01527 if (SelectT2AddrModeImm8Offset(N, LD->getOffset(), Offset)) { 01528 switch (LoadedVT.getSimpleVT().SimpleTy) { 01529 case MVT::i32: 01530 Opcode = isPre ? ARM::t2LDR_PRE : ARM::t2LDR_POST; 01531 break; 01532 case MVT::i16: 01533 if (isSExtLd) 01534 Opcode = isPre ? ARM::t2LDRSH_PRE : ARM::t2LDRSH_POST; 01535 else 01536 Opcode = isPre ? ARM::t2LDRH_PRE : ARM::t2LDRH_POST; 01537 break; 01538 case MVT::i8: 01539 case MVT::i1: 01540 if (isSExtLd) 01541 Opcode = isPre ? ARM::t2LDRSB_PRE : ARM::t2LDRSB_POST; 01542 else 01543 Opcode = isPre ? ARM::t2LDRB_PRE : ARM::t2LDRB_POST; 01544 break; 01545 default: 01546 return nullptr; 01547 } 01548 Match = true; 01549 } 01550 01551 if (Match) { 01552 SDValue Chain = LD->getChain(); 01553 SDValue Base = LD->getBasePtr(); 01554 SDValue Ops[]= { Base, Offset, getAL(CurDAG), 01555 CurDAG->getRegister(0, MVT::i32), Chain }; 01556 return CurDAG->getMachineNode(Opcode, SDLoc(N), MVT::i32, MVT::i32, 01557 MVT::Other, Ops); 01558 } 01559 01560 return nullptr; 01561 } 01562 01563 /// \brief Form a GPRPair pseudo register from a pair of GPR regs. 01564 SDNode *ARMDAGToDAGISel::createGPRPairNode(EVT VT, SDValue V0, SDValue V1) { 01565 SDLoc dl(V0.getNode()); 01566 SDValue RegClass = 01567 CurDAG->getTargetConstant(ARM::GPRPairRegClassID, MVT::i32); 01568 SDValue SubReg0 = CurDAG->getTargetConstant(ARM::gsub_0, MVT::i32); 01569 SDValue SubReg1 = CurDAG->getTargetConstant(ARM::gsub_1, MVT::i32); 01570 const SDValue Ops[] = { RegClass, V0, SubReg0, V1, SubReg1 }; 01571 return CurDAG->getMachineNode(TargetOpcode::REG_SEQUENCE, dl, VT, Ops); 01572 } 01573 01574 /// \brief Form a D register from a pair of S registers. 01575 SDNode *ARMDAGToDAGISel::createSRegPairNode(EVT VT, SDValue V0, SDValue V1) { 01576 SDLoc dl(V0.getNode()); 01577 SDValue RegClass = 01578 CurDAG->getTargetConstant(ARM::DPR_VFP2RegClassID, MVT::i32); 01579 SDValue SubReg0 = CurDAG->getTargetConstant(ARM::ssub_0, MVT::i32); 01580 SDValue SubReg1 = CurDAG->getTargetConstant(ARM::ssub_1, MVT::i32); 01581 const SDValue Ops[] = { RegClass, V0, SubReg0, V1, SubReg1 }; 01582 return CurDAG->getMachineNode(TargetOpcode::REG_SEQUENCE, dl, VT, Ops); 01583 } 01584 01585 /// \brief Form a quad register from a pair of D registers. 01586 SDNode *ARMDAGToDAGISel::createDRegPairNode(EVT VT, SDValue V0, SDValue V1) { 01587 SDLoc dl(V0.getNode()); 01588 SDValue RegClass = CurDAG->getTargetConstant(ARM::QPRRegClassID, MVT::i32); 01589 SDValue SubReg0 = CurDAG->getTargetConstant(ARM::dsub_0, MVT::i32); 01590 SDValue SubReg1 = CurDAG->getTargetConstant(ARM::dsub_1, MVT::i32); 01591 const SDValue Ops[] = { RegClass, V0, SubReg0, V1, SubReg1 }; 01592 return CurDAG->getMachineNode(TargetOpcode::REG_SEQUENCE, dl, VT, Ops); 01593 } 01594 01595 /// \brief Form 4 consecutive D registers from a pair of Q registers. 01596 SDNode *ARMDAGToDAGISel::createQRegPairNode(EVT VT, SDValue V0, SDValue V1) { 01597 SDLoc dl(V0.getNode()); 01598 SDValue RegClass = CurDAG->getTargetConstant(ARM::QQPRRegClassID, MVT::i32); 01599 SDValue SubReg0 = CurDAG->getTargetConstant(ARM::qsub_0, MVT::i32); 01600 SDValue SubReg1 = CurDAG->getTargetConstant(ARM::qsub_1, MVT::i32); 01601 const SDValue Ops[] = { RegClass, V0, SubReg0, V1, SubReg1 }; 01602 return CurDAG->getMachineNode(TargetOpcode::REG_SEQUENCE, dl, VT, Ops); 01603 } 01604 01605 /// \brief Form 4 consecutive S registers. 01606 SDNode *ARMDAGToDAGISel::createQuadSRegsNode(EVT VT, SDValue V0, SDValue V1, 01607 SDValue V2, SDValue V3) { 01608 SDLoc dl(V0.getNode()); 01609 SDValue RegClass = 01610 CurDAG->getTargetConstant(ARM::QPR_VFP2RegClassID, MVT::i32); 01611 SDValue SubReg0 = CurDAG->getTargetConstant(ARM::ssub_0, MVT::i32); 01612 SDValue SubReg1 = CurDAG->getTargetConstant(ARM::ssub_1, MVT::i32); 01613 SDValue SubReg2 = CurDAG->getTargetConstant(ARM::ssub_2, MVT::i32); 01614 SDValue SubReg3 = CurDAG->getTargetConstant(ARM::ssub_3, MVT::i32); 01615 const SDValue Ops[] = { RegClass, V0, SubReg0, V1, SubReg1, 01616 V2, SubReg2, V3, SubReg3 }; 01617 return CurDAG->getMachineNode(TargetOpcode::REG_SEQUENCE, dl, VT, Ops); 01618 } 01619 01620 /// \brief Form 4 consecutive D registers. 01621 SDNode *ARMDAGToDAGISel::createQuadDRegsNode(EVT VT, SDValue V0, SDValue V1, 01622 SDValue V2, SDValue V3) { 01623 SDLoc dl(V0.getNode()); 01624 SDValue RegClass = CurDAG->getTargetConstant(ARM::QQPRRegClassID, MVT::i32); 01625 SDValue SubReg0 = CurDAG->getTargetConstant(ARM::dsub_0, MVT::i32); 01626 SDValue SubReg1 = CurDAG->getTargetConstant(ARM::dsub_1, MVT::i32); 01627 SDValue SubReg2 = CurDAG->getTargetConstant(ARM::dsub_2, MVT::i32); 01628 SDValue SubReg3 = CurDAG->getTargetConstant(ARM::dsub_3, MVT::i32); 01629 const SDValue Ops[] = { RegClass, V0, SubReg0, V1, SubReg1, 01630 V2, SubReg2, V3, SubReg3 }; 01631 return CurDAG->getMachineNode(TargetOpcode::REG_SEQUENCE, dl, VT, Ops); 01632 } 01633 01634 /// \brief Form 4 consecutive Q registers. 01635 SDNode *ARMDAGToDAGISel::createQuadQRegsNode(EVT VT, SDValue V0, SDValue V1, 01636 SDValue V2, SDValue V3) { 01637 SDLoc dl(V0.getNode()); 01638 SDValue RegClass = CurDAG->getTargetConstant(ARM::QQQQPRRegClassID, MVT::i32); 01639 SDValue SubReg0 = CurDAG->getTargetConstant(ARM::qsub_0, MVT::i32); 01640 SDValue SubReg1 = CurDAG->getTargetConstant(ARM::qsub_1, MVT::i32); 01641 SDValue SubReg2 = CurDAG->getTargetConstant(ARM::qsub_2, MVT::i32); 01642 SDValue SubReg3 = CurDAG->getTargetConstant(ARM::qsub_3, MVT::i32); 01643 const SDValue Ops[] = { RegClass, V0, SubReg0, V1, SubReg1, 01644 V2, SubReg2, V3, SubReg3 }; 01645 return CurDAG->getMachineNode(TargetOpcode::REG_SEQUENCE, dl, VT, Ops); 01646 } 01647 01648 /// GetVLDSTAlign - Get the alignment (in bytes) for the alignment operand 01649 /// of a NEON VLD or VST instruction. The supported values depend on the 01650 /// number of registers being loaded. 01651 SDValue ARMDAGToDAGISel::GetVLDSTAlign(SDValue Align, unsigned NumVecs, 01652 bool is64BitVector) { 01653 unsigned NumRegs = NumVecs; 01654 if (!is64BitVector && NumVecs < 3) 01655 NumRegs *= 2; 01656 01657 unsigned Alignment = cast<ConstantSDNode>(Align)->getZExtValue(); 01658 if (Alignment >= 32 && NumRegs == 4) 01659 Alignment = 32; 01660 else if (Alignment >= 16 && (NumRegs == 2 || NumRegs == 4)) 01661 Alignment = 16; 01662 else if (Alignment >= 8) 01663 Alignment = 8; 01664 else 01665 Alignment = 0; 01666 01667 return CurDAG->getTargetConstant(Alignment, MVT::i32); 01668 } 01669 01670 static bool isVLDfixed(unsigned Opc) 01671 { 01672 switch (Opc) { 01673 default: return false; 01674 case ARM::VLD1d8wb_fixed : return true; 01675 case ARM::VLD1d16wb_fixed : return true; 01676 case ARM::VLD1d64Qwb_fixed : return true; 01677 case ARM::VLD1d32wb_fixed : return true; 01678 case ARM::VLD1d64wb_fixed : return true; 01679 case ARM::VLD1d64TPseudoWB_fixed : return true; 01680 case ARM::VLD1d64QPseudoWB_fixed : return true; 01681 case ARM::VLD1q8wb_fixed : return true; 01682 case ARM::VLD1q16wb_fixed : return true; 01683 case ARM::VLD1q32wb_fixed : return true; 01684 case ARM::VLD1q64wb_fixed : return true; 01685 case ARM::VLD2d8wb_fixed : return true; 01686 case ARM::VLD2d16wb_fixed : return true; 01687 case ARM::VLD2d32wb_fixed : return true; 01688 case ARM::VLD2q8PseudoWB_fixed : return true; 01689 case ARM::VLD2q16PseudoWB_fixed : return true; 01690 case ARM::VLD2q32PseudoWB_fixed : return true; 01691 case ARM::VLD2DUPd8wb_fixed : return true; 01692 case ARM::VLD2DUPd16wb_fixed : return true; 01693 case ARM::VLD2DUPd32wb_fixed : return true; 01694 } 01695 } 01696 01697 static bool isVSTfixed(unsigned Opc) 01698 { 01699 switch (Opc) { 01700 default: return false; 01701 case ARM::VST1d8wb_fixed : return true; 01702 case ARM::VST1d16wb_fixed : return true; 01703 case ARM::VST1d32wb_fixed : return true; 01704 case ARM::VST1d64wb_fixed : return true; 01705 case ARM::VST1q8wb_fixed : return true; 01706 case ARM::VST1q16wb_fixed : return true; 01707 case ARM::VST1q32wb_fixed : return true; 01708 case ARM::VST1q64wb_fixed : return true; 01709 case ARM::VST1d64TPseudoWB_fixed : return true; 01710 case ARM::VST1d64QPseudoWB_fixed : return true; 01711 case ARM::VST2d8wb_fixed : return true; 01712 case ARM::VST2d16wb_fixed : return true; 01713 case ARM::VST2d32wb_fixed : return true; 01714 case ARM::VST2q8PseudoWB_fixed : return true; 01715 case ARM::VST2q16PseudoWB_fixed : return true; 01716 case ARM::VST2q32PseudoWB_fixed : return true; 01717 } 01718 } 01719 01720 // Get the register stride update opcode of a VLD/VST instruction that 01721 // is otherwise equivalent to the given fixed stride updating instruction. 01722 static unsigned getVLDSTRegisterUpdateOpcode(unsigned Opc) { 01723 assert((isVLDfixed(Opc) || isVSTfixed(Opc)) 01724 && "Incorrect fixed stride updating instruction."); 01725 switch (Opc) { 01726 default: break; 01727 case ARM::VLD1d8wb_fixed: return ARM::VLD1d8wb_register; 01728 case ARM::VLD1d16wb_fixed: return ARM::VLD1d16wb_register; 01729 case ARM::VLD1d32wb_fixed: return ARM::VLD1d32wb_register; 01730 case ARM::VLD1d64wb_fixed: return ARM::VLD1d64wb_register; 01731 case ARM::VLD1q8wb_fixed: return ARM::VLD1q8wb_register; 01732 case ARM::VLD1q16wb_fixed: return ARM::VLD1q16wb_register; 01733 case ARM::VLD1q32wb_fixed: return ARM::VLD1q32wb_register; 01734 case ARM::VLD1q64wb_fixed: return ARM::VLD1q64wb_register; 01735 case ARM::VLD1d64Twb_fixed: return ARM::VLD1d64Twb_register; 01736 case ARM::VLD1d64Qwb_fixed: return ARM::VLD1d64Qwb_register; 01737 case ARM::VLD1d64TPseudoWB_fixed: return ARM::VLD1d64TPseudoWB_register; 01738 case ARM::VLD1d64QPseudoWB_fixed: return ARM::VLD1d64QPseudoWB_register; 01739 01740 case ARM::VST1d8wb_fixed: return ARM::VST1d8wb_register; 01741 case ARM::VST1d16wb_fixed: return ARM::VST1d16wb_register; 01742 case ARM::VST1d32wb_fixed: return ARM::VST1d32wb_register; 01743 case ARM::VST1d64wb_fixed: return ARM::VST1d64wb_register; 01744 case ARM::VST1q8wb_fixed: return ARM::VST1q8wb_register; 01745 case ARM::VST1q16wb_fixed: return ARM::VST1q16wb_register; 01746 case ARM::VST1q32wb_fixed: return ARM::VST1q32wb_register; 01747 case ARM::VST1q64wb_fixed: return ARM::VST1q64wb_register; 01748 case ARM::VST1d64TPseudoWB_fixed: return ARM::VST1d64TPseudoWB_register; 01749 case ARM::VST1d64QPseudoWB_fixed: return ARM::VST1d64QPseudoWB_register; 01750 01751 case ARM::VLD2d8wb_fixed: return ARM::VLD2d8wb_register; 01752 case ARM::VLD2d16wb_fixed: return ARM::VLD2d16wb_register; 01753 case ARM::VLD2d32wb_fixed: return ARM::VLD2d32wb_register; 01754 case ARM::VLD2q8PseudoWB_fixed: return ARM::VLD2q8PseudoWB_register; 01755 case ARM::VLD2q16PseudoWB_fixed: return ARM::VLD2q16PseudoWB_register; 01756 case ARM::VLD2q32PseudoWB_fixed: return ARM::VLD2q32PseudoWB_register; 01757 01758 case ARM::VST2d8wb_fixed: return ARM::VST2d8wb_register; 01759 case ARM::VST2d16wb_fixed: return ARM::VST2d16wb_register; 01760 case ARM::VST2d32wb_fixed: return ARM::VST2d32wb_register; 01761 case ARM::VST2q8PseudoWB_fixed: return ARM::VST2q8PseudoWB_register; 01762 case ARM::VST2q16PseudoWB_fixed: return ARM::VST2q16PseudoWB_register; 01763 case ARM::VST2q32PseudoWB_fixed: return ARM::VST2q32PseudoWB_register; 01764 01765 case ARM::VLD2DUPd8wb_fixed: return ARM::VLD2DUPd8wb_register; 01766 case ARM::VLD2DUPd16wb_fixed: return ARM::VLD2DUPd16wb_register; 01767 case ARM::VLD2DUPd32wb_fixed: return ARM::VLD2DUPd32wb_register; 01768 } 01769 return Opc; // If not one we handle, return it unchanged. 01770 } 01771 01772 SDNode *ARMDAGToDAGISel::SelectVLD(SDNode *N, bool isUpdating, unsigned NumVecs, 01773 const uint16_t *DOpcodes, 01774 const uint16_t *QOpcodes0, 01775 const uint16_t *QOpcodes1) { 01776 assert(NumVecs >= 1 && NumVecs <= 4 && "VLD NumVecs out-of-range"); 01777 SDLoc dl(N); 01778 01779 SDValue MemAddr, Align; 01780 unsigned AddrOpIdx = isUpdating ? 1 : 2; 01781 if (!SelectAddrMode6(N, N->getOperand(AddrOpIdx), MemAddr, Align)) 01782 return nullptr; 01783 01784 SDValue Chain = N->getOperand(0); 01785 EVT VT = N->getValueType(0); 01786 bool is64BitVector = VT.is64BitVector(); 01787 Align = GetVLDSTAlign(Align, NumVecs, is64BitVector); 01788 01789 unsigned OpcodeIndex; 01790 switch (VT.getSimpleVT().SimpleTy) { 01791 default: llvm_unreachable("unhandled vld type"); 01792 // Double-register operations: 01793 case MVT::v8i8: OpcodeIndex = 0; break; 01794 case MVT::v4i16: OpcodeIndex = 1; break; 01795 case MVT::v2f32: 01796 case MVT::v2i32: OpcodeIndex = 2; break; 01797 case MVT::v1i64: OpcodeIndex = 3; break; 01798 // Quad-register operations: 01799 case MVT::v16i8: OpcodeIndex = 0; break; 01800 case MVT::v8i16: OpcodeIndex = 1; break; 01801 case MVT::v4f32: 01802 case MVT::v4i32: OpcodeIndex = 2; break; 01803 case MVT::v2i64: OpcodeIndex = 3; 01804 assert(NumVecs == 1 && "v2i64 type only supported for VLD1"); 01805 break; 01806 } 01807 01808 EVT ResTy; 01809 if (NumVecs == 1) 01810 ResTy = VT; 01811 else { 01812 unsigned ResTyElts = (NumVecs == 3) ? 4 : NumVecs; 01813 if (!is64BitVector) 01814 ResTyElts *= 2; 01815 ResTy = EVT::getVectorVT(*CurDAG->getContext(), MVT::i64, ResTyElts); 01816 } 01817 std::vector<EVT> ResTys; 01818 ResTys.push_back(ResTy); 01819 if (isUpdating) 01820 ResTys.push_back(MVT::i32); 01821 ResTys.push_back(MVT::Other); 01822 01823 SDValue Pred = getAL(CurDAG); 01824 SDValue Reg0 = CurDAG->getRegister(0, MVT::i32); 01825 SDNode *VLd; 01826 SmallVector<SDValue, 7> Ops; 01827 01828 // Double registers and VLD1/VLD2 quad registers are directly supported. 01829 if (is64BitVector || NumVecs <= 2) { 01830 unsigned Opc = (is64BitVector ? DOpcodes[OpcodeIndex] : 01831 QOpcodes0[OpcodeIndex]); 01832 Ops.push_back(MemAddr); 01833 Ops.push_back(Align); 01834 if (isUpdating) { 01835 SDValue Inc = N->getOperand(AddrOpIdx + 1); 01836 // FIXME: VLD1/VLD2 fixed increment doesn't need Reg0. Remove the reg0 01837 // case entirely when the rest are updated to that form, too. 01838 if ((NumVecs <= 2) && !isa<ConstantSDNode>(Inc.getNode())) 01839 Opc = getVLDSTRegisterUpdateOpcode(Opc); 01840 // FIXME: We use a VLD1 for v1i64 even if the pseudo says vld2/3/4, so 01841 // check for that explicitly too. Horribly hacky, but temporary. 01842 if ((NumVecs > 2 && !isVLDfixed(Opc)) || 01843 !isa<ConstantSDNode>(Inc.getNode())) 01844 Ops.push_back(isa<ConstantSDNode>(Inc.getNode()) ? Reg0 : Inc); 01845 } 01846 Ops.push_back(Pred); 01847 Ops.push_back(Reg0); 01848 Ops.push_back(Chain); 01849 VLd = CurDAG->getMachineNode(Opc, dl, ResTys, Ops); 01850 01851 } else { 01852 // Otherwise, quad registers are loaded with two separate instructions, 01853 // where one loads the even registers and the other loads the odd registers. 01854 EVT AddrTy = MemAddr.getValueType(); 01855 01856 // Load the even subregs. This is always an updating load, so that it 01857 // provides the address to the second load for the odd subregs. 01858 SDValue ImplDef = 01859 SDValue(CurDAG->getMachineNode(TargetOpcode::IMPLICIT_DEF, dl, ResTy), 0); 01860 const SDValue OpsA[] = { MemAddr, Align, Reg0, ImplDef, Pred, Reg0, Chain }; 01861 SDNode *VLdA = CurDAG->getMachineNode(QOpcodes0[OpcodeIndex], dl, 01862 ResTy, AddrTy, MVT::Other, OpsA); 01863 Chain = SDValue(VLdA, 2); 01864 01865 // Load the odd subregs. 01866 Ops.push_back(SDValue(VLdA, 1)); 01867 Ops.push_back(Align); 01868 if (isUpdating) { 01869 SDValue Inc = N->getOperand(AddrOpIdx + 1); 01870 assert(isa<ConstantSDNode>(Inc.getNode()) && 01871 "only constant post-increment update allowed for VLD3/4"); 01872 (void)Inc; 01873 Ops.push_back(Reg0); 01874 } 01875 Ops.push_back(SDValue(VLdA, 0)); 01876 Ops.push_back(Pred); 01877 Ops.push_back(Reg0); 01878 Ops.push_back(Chain); 01879 VLd = CurDAG->getMachineNode(QOpcodes1[OpcodeIndex], dl, ResTys, Ops); 01880 } 01881 01882 // Transfer memoperands. 01883 MachineSDNode::mmo_iterator MemOp = MF->allocateMemRefsArray(1); 01884 MemOp[0] = cast<MemIntrinsicSDNode>(N)->getMemOperand(); 01885 cast<MachineSDNode>(VLd)->setMemRefs(MemOp, MemOp + 1); 01886 01887 if (NumVecs == 1) 01888 return VLd; 01889 01890 // Extract out the subregisters. 01891 SDValue SuperReg = SDValue(VLd, 0); 01892 assert(ARM::dsub_7 == ARM::dsub_0+7 && 01893 ARM::qsub_3 == ARM::qsub_0+3 && "Unexpected subreg numbering"); 01894 unsigned Sub0 = (is64BitVector ? ARM::dsub_0 : ARM::qsub_0); 01895 for (unsigned Vec = 0; Vec < NumVecs; ++Vec) 01896 ReplaceUses(SDValue(N, Vec), 01897 CurDAG->getTargetExtractSubreg(Sub0 + Vec, dl, VT, SuperReg)); 01898 ReplaceUses(SDValue(N, NumVecs), SDValue(VLd, 1)); 01899 if (isUpdating) 01900 ReplaceUses(SDValue(N, NumVecs + 1), SDValue(VLd, 2)); 01901 return nullptr; 01902 } 01903 01904 SDNode *ARMDAGToDAGISel::SelectVST(SDNode *N, bool isUpdating, unsigned NumVecs, 01905 const uint16_t *DOpcodes, 01906 const uint16_t *QOpcodes0, 01907 const uint16_t *QOpcodes1) { 01908 assert(NumVecs >= 1 && NumVecs <= 4 && "VST NumVecs out-of-range"); 01909 SDLoc dl(N); 01910 01911 SDValue MemAddr, Align; 01912 unsigned AddrOpIdx = isUpdating ? 1 : 2; 01913 unsigned Vec0Idx = 3; // AddrOpIdx + (isUpdating ? 2 : 1) 01914 if (!SelectAddrMode6(N, N->getOperand(AddrOpIdx), MemAddr, Align)) 01915 return nullptr; 01916 01917 MachineSDNode::mmo_iterator MemOp = MF->allocateMemRefsArray(1); 01918 MemOp[0] = cast<MemIntrinsicSDNode>(N)->getMemOperand(); 01919 01920 SDValue Chain = N->getOperand(0); 01921 EVT VT = N->getOperand(Vec0Idx).getValueType(); 01922 bool is64BitVector = VT.is64BitVector(); 01923 Align = GetVLDSTAlign(Align, NumVecs, is64BitVector); 01924 01925 unsigned OpcodeIndex; 01926 switch (VT.getSimpleVT().SimpleTy) { 01927 default: llvm_unreachable("unhandled vst type"); 01928 // Double-register operations: 01929 case MVT::v8i8: OpcodeIndex = 0; break; 01930 case MVT::v4i16: OpcodeIndex = 1; break; 01931 case MVT::v2f32: 01932 case MVT::v2i32: OpcodeIndex = 2; break; 01933 case MVT::v1i64: OpcodeIndex = 3; break; 01934 // Quad-register operations: 01935 case MVT::v16i8: OpcodeIndex = 0; break; 01936 case MVT::v8i16: OpcodeIndex = 1; break; 01937 case MVT::v4f32: 01938 case MVT::v4i32: OpcodeIndex = 2; break; 01939 case MVT::v2i64: OpcodeIndex = 3; 01940 assert(NumVecs == 1 && "v2i64 type only supported for VST1"); 01941 break; 01942 } 01943 01944 std::vector<EVT> ResTys; 01945 if (isUpdating) 01946 ResTys.push_back(MVT::i32); 01947 ResTys.push_back(MVT::Other); 01948 01949 SDValue Pred = getAL(CurDAG); 01950 SDValue Reg0 = CurDAG->getRegister(0, MVT::i32); 01951 SmallVector<SDValue, 7> Ops; 01952 01953 // Double registers and VST1/VST2 quad registers are directly supported. 01954 if (is64BitVector || NumVecs <= 2) { 01955 SDValue SrcReg; 01956 if (NumVecs == 1) { 01957 SrcReg = N->getOperand(Vec0Idx); 01958 } else if (is64BitVector) { 01959 // Form a REG_SEQUENCE to force register allocation. 01960 SDValue V0 = N->getOperand(Vec0Idx + 0); 01961 SDValue V1 = N->getOperand(Vec0Idx + 1); 01962 if (NumVecs == 2) 01963 SrcReg = SDValue(createDRegPairNode(MVT::v2i64, V0, V1), 0); 01964 else { 01965 SDValue V2 = N->getOperand(Vec0Idx + 2); 01966 // If it's a vst3, form a quad D-register and leave the last part as 01967 // an undef. 01968 SDValue V3 = (NumVecs == 3) 01969 ? SDValue(CurDAG->getMachineNode(TargetOpcode::IMPLICIT_DEF,dl,VT), 0) 01970 : N->getOperand(Vec0Idx + 3); 01971 SrcReg = SDValue(createQuadDRegsNode(MVT::v4i64, V0, V1, V2, V3), 0); 01972 } 01973 } else { 01974 // Form a QQ register. 01975 SDValue Q0 = N->getOperand(Vec0Idx); 01976 SDValue Q1 = N->getOperand(Vec0Idx + 1); 01977 SrcReg = SDValue(createQRegPairNode(MVT::v4i64, Q0, Q1), 0); 01978 } 01979 01980 unsigned Opc = (is64BitVector ? DOpcodes[OpcodeIndex] : 01981 QOpcodes0[OpcodeIndex]); 01982 Ops.push_back(MemAddr); 01983 Ops.push_back(Align); 01984 if (isUpdating) { 01985 SDValue Inc = N->getOperand(AddrOpIdx + 1); 01986 // FIXME: VST1/VST2 fixed increment doesn't need Reg0. Remove the reg0 01987 // case entirely when the rest are updated to that form, too. 01988 if (NumVecs <= 2 && !isa<ConstantSDNode>(Inc.getNode())) 01989 Opc = getVLDSTRegisterUpdateOpcode(Opc); 01990 // FIXME: We use a VST1 for v1i64 even if the pseudo says vld2/3/4, so 01991 // check for that explicitly too. Horribly hacky, but temporary. 01992 if (!isa<ConstantSDNode>(Inc.getNode())) 01993 Ops.push_back(Inc); 01994 else if (NumVecs > 2 && !isVSTfixed(Opc)) 01995 Ops.push_back(Reg0); 01996 } 01997 Ops.push_back(SrcReg); 01998 Ops.push_back(Pred); 01999 Ops.push_back(Reg0); 02000 Ops.push_back(Chain); 02001 SDNode *VSt = CurDAG->getMachineNode(Opc, dl, ResTys, Ops); 02002 02003 // Transfer memoperands. 02004 cast<MachineSDNode>(VSt)->setMemRefs(MemOp, MemOp + 1); 02005 02006 return VSt; 02007 } 02008 02009 // Otherwise, quad registers are stored with two separate instructions, 02010 // where one stores the even registers and the other stores the odd registers. 02011 02012 // Form the QQQQ REG_SEQUENCE. 02013 SDValue V0 = N->getOperand(Vec0Idx + 0); 02014 SDValue V1 = N->getOperand(Vec0Idx + 1); 02015 SDValue V2 = N->getOperand(Vec0Idx + 2); 02016 SDValue V3 = (NumVecs == 3) 02017 ? SDValue(CurDAG->getMachineNode(TargetOpcode::IMPLICIT_DEF, dl, VT), 0) 02018 : N->getOperand(Vec0Idx + 3); 02019 SDValue RegSeq = SDValue(createQuadQRegsNode(MVT::v8i64, V0, V1, V2, V3), 0); 02020 02021 // Store the even D registers. This is always an updating store, so that it 02022 // provides the address to the second store for the odd subregs. 02023 const SDValue OpsA[] = { MemAddr, Align, Reg0, RegSeq, Pred, Reg0, Chain }; 02024 SDNode *VStA = CurDAG->getMachineNode(QOpcodes0[OpcodeIndex], dl, 02025 MemAddr.getValueType(), 02026 MVT::Other, OpsA); 02027 cast<MachineSDNode>(VStA)->setMemRefs(MemOp, MemOp + 1); 02028 Chain = SDValue(VStA, 1); 02029 02030 // Store the odd D registers. 02031 Ops.push_back(SDValue(VStA, 0)); 02032 Ops.push_back(Align); 02033 if (isUpdating) { 02034 SDValue Inc = N->getOperand(AddrOpIdx + 1); 02035 assert(isa<ConstantSDNode>(Inc.getNode()) && 02036 "only constant post-increment update allowed for VST3/4"); 02037 (void)Inc; 02038 Ops.push_back(Reg0); 02039 } 02040 Ops.push_back(RegSeq); 02041 Ops.push_back(Pred); 02042 Ops.push_back(Reg0); 02043 Ops.push_back(Chain); 02044 SDNode *VStB = CurDAG->getMachineNode(QOpcodes1[OpcodeIndex], dl, ResTys, 02045 Ops); 02046 cast<MachineSDNode>(VStB)->setMemRefs(MemOp, MemOp + 1); 02047 return VStB; 02048 } 02049 02050 SDNode *ARMDAGToDAGISel::SelectVLDSTLane(SDNode *N, bool IsLoad, 02051 bool isUpdating, unsigned NumVecs, 02052 const uint16_t *DOpcodes, 02053 const uint16_t *QOpcodes) { 02054 assert(NumVecs >=2 && NumVecs <= 4 && "VLDSTLane NumVecs out-of-range"); 02055 SDLoc dl(N); 02056 02057 SDValue MemAddr, Align; 02058 unsigned AddrOpIdx = isUpdating ? 1 : 2; 02059 unsigned Vec0Idx = 3; // AddrOpIdx + (isUpdating ? 2 : 1) 02060 if (!SelectAddrMode6(N, N->getOperand(AddrOpIdx), MemAddr, Align)) 02061 return nullptr; 02062 02063 MachineSDNode::mmo_iterator MemOp = MF->allocateMemRefsArray(1); 02064 MemOp[0] = cast<MemIntrinsicSDNode>(N)->getMemOperand(); 02065 02066 SDValue Chain = N->getOperand(0); 02067 unsigned Lane = 02068 cast<ConstantSDNode>(N->getOperand(Vec0Idx + NumVecs))->getZExtValue(); 02069 EVT VT = N->getOperand(Vec0Idx).getValueType(); 02070 bool is64BitVector = VT.is64BitVector(); 02071 02072 unsigned Alignment = 0; 02073 if (NumVecs != 3) { 02074 Alignment = cast<ConstantSDNode>(Align)->getZExtValue(); 02075 unsigned NumBytes = NumVecs * VT.getVectorElementType().getSizeInBits()/8; 02076 if (Alignment > NumBytes) 02077 Alignment = NumBytes; 02078 if (Alignment < 8 && Alignment < NumBytes) 02079 Alignment = 0; 02080 // Alignment must be a power of two; make sure of that. 02081 Alignment = (Alignment & -Alignment); 02082 if (Alignment == 1) 02083 Alignment = 0; 02084 } 02085 Align = CurDAG->getTargetConstant(Alignment, MVT::i32); 02086 02087 unsigned OpcodeIndex; 02088 switch (VT.getSimpleVT().SimpleTy) { 02089 default: llvm_unreachable("unhandled vld/vst lane type"); 02090 // Double-register operations: 02091 case MVT::v8i8: OpcodeIndex = 0; break; 02092 case MVT::v4i16: OpcodeIndex = 1; break; 02093 case MVT::v2f32: 02094 case MVT::v2i32: OpcodeIndex = 2; break; 02095 // Quad-register operations: 02096 case MVT::v8i16: OpcodeIndex = 0; break; 02097 case MVT::v4f32: 02098 case MVT::v4i32: OpcodeIndex = 1; break; 02099 } 02100 02101 std::vector<EVT> ResTys; 02102 if (IsLoad) { 02103 unsigned ResTyElts = (NumVecs == 3) ? 4 : NumVecs; 02104 if (!is64BitVector) 02105 ResTyElts *= 2; 02106 ResTys.push_back(EVT::getVectorVT(*CurDAG->getContext(), 02107 MVT::i64, ResTyElts)); 02108 } 02109 if (isUpdating) 02110 ResTys.push_back(MVT::i32); 02111 ResTys.push_back(MVT::Other); 02112 02113 SDValue Pred = getAL(CurDAG); 02114 SDValue Reg0 = CurDAG->getRegister(0, MVT::i32); 02115 02116 SmallVector<SDValue, 8> Ops; 02117 Ops.push_back(MemAddr); 02118 Ops.push_back(Align); 02119 if (isUpdating) { 02120 SDValue Inc = N->getOperand(AddrOpIdx + 1); 02121 Ops.push_back(isa<ConstantSDNode>(Inc.getNode()) ? Reg0 : Inc); 02122 } 02123 02124 SDValue SuperReg; 02125 SDValue V0 = N->getOperand(Vec0Idx + 0); 02126 SDValue V1 = N->getOperand(Vec0Idx + 1); 02127 if (NumVecs == 2) { 02128 if (is64BitVector) 02129 SuperReg = SDValue(createDRegPairNode(MVT::v2i64, V0, V1), 0); 02130 else 02131 SuperReg = SDValue(createQRegPairNode(MVT::v4i64, V0, V1), 0); 02132 } else { 02133 SDValue V2 = N->getOperand(Vec0Idx + 2); 02134 SDValue V3 = (NumVecs == 3) 02135 ? SDValue(CurDAG->getMachineNode(TargetOpcode::IMPLICIT_DEF, dl, VT), 0) 02136 : N->getOperand(Vec0Idx + 3); 02137 if (is64BitVector) 02138 SuperReg = SDValue(createQuadDRegsNode(MVT::v4i64, V0, V1, V2, V3), 0); 02139 else 02140 SuperReg = SDValue(createQuadQRegsNode(MVT::v8i64, V0, V1, V2, V3), 0); 02141 } 02142 Ops.push_back(SuperReg); 02143 Ops.push_back(getI32Imm(Lane)); 02144 Ops.push_back(Pred); 02145 Ops.push_back(Reg0); 02146 Ops.push_back(Chain); 02147 02148 unsigned Opc = (is64BitVector ? DOpcodes[OpcodeIndex] : 02149 QOpcodes[OpcodeIndex]); 02150 SDNode *VLdLn = CurDAG->getMachineNode(Opc, dl, ResTys, Ops); 02151 cast<MachineSDNode>(VLdLn)->setMemRefs(MemOp, MemOp + 1); 02152 if (!IsLoad) 02153 return VLdLn; 02154 02155 // Extract the subregisters. 02156 SuperReg = SDValue(VLdLn, 0); 02157 assert(ARM::dsub_7 == ARM::dsub_0+7 && 02158 ARM::qsub_3 == ARM::qsub_0+3 && "Unexpected subreg numbering"); 02159 unsigned Sub0 = is64BitVector ? ARM::dsub_0 : ARM::qsub_0; 02160 for (unsigned Vec = 0; Vec < NumVecs; ++Vec) 02161 ReplaceUses(SDValue(N, Vec), 02162 CurDAG->getTargetExtractSubreg(Sub0 + Vec, dl, VT, SuperReg)); 02163 ReplaceUses(SDValue(N, NumVecs), SDValue(VLdLn, 1)); 02164 if (isUpdating) 02165 ReplaceUses(SDValue(N, NumVecs + 1), SDValue(VLdLn, 2)); 02166 return nullptr; 02167 } 02168 02169 SDNode *ARMDAGToDAGISel::SelectVLDDup(SDNode *N, bool isUpdating, 02170 unsigned NumVecs, 02171 const uint16_t *Opcodes) { 02172 assert(NumVecs >=2 && NumVecs <= 4 && "VLDDup NumVecs out-of-range"); 02173 SDLoc dl(N); 02174 02175 SDValue MemAddr, Align; 02176 if (!SelectAddrMode6(N, N->getOperand(1), MemAddr, Align)) 02177 return nullptr; 02178 02179 MachineSDNode::mmo_iterator MemOp = MF->allocateMemRefsArray(1); 02180 MemOp[0] = cast<MemIntrinsicSDNode>(N)->getMemOperand(); 02181 02182 SDValue Chain = N->getOperand(0); 02183 EVT VT = N->getValueType(0); 02184 02185 unsigned Alignment = 0; 02186 if (NumVecs != 3) { 02187 Alignment = cast<ConstantSDNode>(Align)->getZExtValue(); 02188 unsigned NumBytes = NumVecs * VT.getVectorElementType().getSizeInBits()/8; 02189 if (Alignment > NumBytes) 02190 Alignment = NumBytes; 02191 if (Alignment < 8 && Alignment < NumBytes) 02192 Alignment = 0; 02193 // Alignment must be a power of two; make sure of that. 02194 Alignment = (Alignment & -Alignment); 02195 if (Alignment == 1) 02196 Alignment = 0; 02197 } 02198 Align = CurDAG->getTargetConstant(Alignment, MVT::i32); 02199 02200 unsigned OpcodeIndex; 02201 switch (VT.getSimpleVT().SimpleTy) { 02202 default: llvm_unreachable("unhandled vld-dup type"); 02203 case MVT::v8i8: OpcodeIndex = 0; break; 02204 case MVT::v4i16: OpcodeIndex = 1; break; 02205 case MVT::v2f32: 02206 case MVT::v2i32: OpcodeIndex = 2; break; 02207 } 02208 02209 SDValue Pred = getAL(CurDAG); 02210 SDValue Reg0 = CurDAG->getRegister(0, MVT::i32); 02211 SDValue SuperReg; 02212 unsigned Opc = Opcodes[OpcodeIndex]; 02213 SmallVector<SDValue, 6> Ops; 02214 Ops.push_back(MemAddr); 02215 Ops.push_back(Align); 02216 if (isUpdating) { 02217 // fixed-stride update instructions don't have an explicit writeback 02218 // operand. It's implicit in the opcode itself. 02219 SDValue Inc = N->getOperand(2); 02220 if (!isa<ConstantSDNode>(Inc.getNode())) 02221 Ops.push_back(Inc); 02222 // FIXME: VLD3 and VLD4 haven't been updated to that form yet. 02223 else if (NumVecs > 2) 02224 Ops.push_back(Reg0); 02225 } 02226 Ops.push_back(Pred); 02227 Ops.push_back(Reg0); 02228 Ops.push_back(Chain); 02229 02230 unsigned ResTyElts = (NumVecs == 3) ? 4 : NumVecs; 02231 std::vector<EVT> ResTys; 02232 ResTys.push_back(EVT::getVectorVT(*CurDAG->getContext(), MVT::i64,ResTyElts)); 02233 if (isUpdating) 02234 ResTys.push_back(MVT::i32); 02235 ResTys.push_back(MVT::Other); 02236 SDNode *VLdDup = CurDAG->getMachineNode(Opc, dl, ResTys, Ops); 02237 cast<MachineSDNode>(VLdDup)->setMemRefs(MemOp, MemOp + 1); 02238 SuperReg = SDValue(VLdDup, 0); 02239 02240 // Extract the subregisters. 02241 assert(ARM::dsub_7 == ARM::dsub_0+7 && "Unexpected subreg numbering"); 02242 unsigned SubIdx = ARM::dsub_0; 02243 for (unsigned Vec = 0; Vec < NumVecs; ++Vec) 02244 ReplaceUses(SDValue(N, Vec), 02245 CurDAG->getTargetExtractSubreg(SubIdx+Vec, dl, VT, SuperReg)); 02246 ReplaceUses(SDValue(N, NumVecs), SDValue(VLdDup, 1)); 02247 if (isUpdating) 02248 ReplaceUses(SDValue(N, NumVecs + 1), SDValue(VLdDup, 2)); 02249 return nullptr; 02250 } 02251 02252 SDNode *ARMDAGToDAGISel::SelectVTBL(SDNode *N, bool IsExt, unsigned NumVecs, 02253 unsigned Opc) { 02254 assert(NumVecs >= 2 && NumVecs <= 4 && "VTBL NumVecs out-of-range"); 02255 SDLoc dl(N); 02256 EVT VT = N->getValueType(0); 02257 unsigned FirstTblReg = IsExt ? 2 : 1; 02258 02259 // Form a REG_SEQUENCE to force register allocation. 02260 SDValue RegSeq; 02261 SDValue V0 = N->getOperand(FirstTblReg + 0); 02262 SDValue V1 = N->getOperand(FirstTblReg + 1); 02263 if (NumVecs == 2) 02264 RegSeq = SDValue(createDRegPairNode(MVT::v16i8, V0, V1), 0); 02265 else { 02266 SDValue V2 = N->getOperand(FirstTblReg + 2); 02267 // If it's a vtbl3, form a quad D-register and leave the last part as 02268 // an undef. 02269 SDValue V3 = (NumVecs == 3) 02270 ? SDValue(CurDAG->getMachineNode(TargetOpcode::IMPLICIT_DEF, dl, VT), 0) 02271 : N->getOperand(FirstTblReg + 3); 02272 RegSeq = SDValue(createQuadDRegsNode(MVT::v4i64, V0, V1, V2, V3), 0); 02273 } 02274 02275 SmallVector<SDValue, 6> Ops; 02276 if (IsExt) 02277 Ops.push_back(N->getOperand(1)); 02278 Ops.push_back(RegSeq); 02279 Ops.push_back(N->getOperand(FirstTblReg + NumVecs)); 02280 Ops.push_back(getAL(CurDAG)); // predicate 02281 Ops.push_back(CurDAG->getRegister(0, MVT::i32)); // predicate register 02282 return CurDAG->getMachineNode(Opc, dl, VT, Ops); 02283 } 02284 02285 SDNode *ARMDAGToDAGISel::SelectV6T2BitfieldExtractOp(SDNode *N, 02286 bool isSigned) { 02287 if (!Subtarget->hasV6T2Ops()) 02288 return nullptr; 02289 02290 unsigned Opc = isSigned 02291 ? (Subtarget->isThumb() ? ARM::t2SBFX : ARM::SBFX) 02292 : (Subtarget->isThumb() ? ARM::t2UBFX : ARM::UBFX); 02293 02294 // For unsigned extracts, check for a shift right and mask 02295 unsigned And_imm = 0; 02296 if (N->getOpcode() == ISD::AND) { 02297 if (isOpcWithIntImmediate(N, ISD::AND, And_imm)) { 02298 02299 // The immediate is a mask of the low bits iff imm & (imm+1) == 0 02300 if (And_imm & (And_imm + 1)) 02301 return nullptr; 02302 02303 unsigned Srl_imm = 0; 02304 if (isOpcWithIntImmediate(N->getOperand(0).getNode(), ISD::SRL, 02305 Srl_imm)) { 02306 assert(Srl_imm > 0 && Srl_imm < 32 && "bad amount in shift node!"); 02307 02308 // Note: The width operand is encoded as width-1. 02309 unsigned Width = CountTrailingOnes_32(And_imm) - 1; 02310 unsigned LSB = Srl_imm; 02311 02312 SDValue Reg0 = CurDAG->getRegister(0, MVT::i32); 02313 02314 if ((LSB + Width + 1) == N->getValueType(0).getSizeInBits()) { 02315 // It's cheaper to use a right shift to extract the top bits. 02316 if (Subtarget->isThumb()) { 02317 Opc = isSigned ? ARM::t2ASRri : ARM::t2LSRri; 02318 SDValue Ops[] = { N->getOperand(0).getOperand(0), 02319 CurDAG->getTargetConstant(LSB, MVT::i32), 02320 getAL(CurDAG), Reg0, Reg0 }; 02321 return CurDAG->SelectNodeTo(N, Opc, MVT::i32, Ops); 02322 } 02323 02324 // ARM models shift instructions as MOVsi with shifter operand. 02325 ARM_AM::ShiftOpc ShOpcVal = ARM_AM::getShiftOpcForNode(ISD::SRL); 02326 SDValue ShOpc = 02327 CurDAG->getTargetConstant(ARM_AM::getSORegOpc(ShOpcVal, LSB), 02328 MVT::i32); 02329 SDValue Ops[] = { N->getOperand(0).getOperand(0), ShOpc, 02330 getAL(CurDAG), Reg0, Reg0 }; 02331 return CurDAG->SelectNodeTo(N, ARM::MOVsi, MVT::i32, Ops); 02332 } 02333 02334 SDValue Ops[] = { N->getOperand(0).getOperand(0), 02335 CurDAG->getTargetConstant(LSB, MVT::i32), 02336 CurDAG->getTargetConstant(Width, MVT::i32), 02337 getAL(CurDAG), Reg0 }; 02338 return CurDAG->SelectNodeTo(N, Opc, MVT::i32, Ops); 02339 } 02340 } 02341 return nullptr; 02342 } 02343 02344 // Otherwise, we're looking for a shift of a shift 02345 unsigned Shl_imm = 0; 02346 if (isOpcWithIntImmediate(N->getOperand(0).getNode(), ISD::SHL, Shl_imm)) { 02347 assert(Shl_imm > 0 && Shl_imm < 32 && "bad amount in shift node!"); 02348 unsigned Srl_imm = 0; 02349 if (isInt32Immediate(N->getOperand(1), Srl_imm)) { 02350 assert(Srl_imm > 0 && Srl_imm < 32 && "bad amount in shift node!"); 02351 // Note: The width operand is encoded as width-1. 02352 unsigned Width = 32 - Srl_imm - 1; 02353 int LSB = Srl_imm - Shl_imm; 02354 if (LSB < 0) 02355 return nullptr; 02356 SDValue Reg0 = CurDAG->getRegister(0, MVT::i32); 02357 SDValue Ops[] = { N->getOperand(0).getOperand(0), 02358 CurDAG->getTargetConstant(LSB, MVT::i32), 02359 CurDAG->getTargetConstant(Width, MVT::i32), 02360 getAL(CurDAG), Reg0 }; 02361 return CurDAG->SelectNodeTo(N, Opc, MVT::i32, Ops); 02362 } 02363 } 02364 02365 if (N->getOpcode() == ISD::SIGN_EXTEND_INREG) { 02366 unsigned Width = cast<VTSDNode>(N->getOperand(1))->getVT().getSizeInBits(); 02367 unsigned LSB = 0; 02368 if (!isOpcWithIntImmediate(N->getOperand(0).getNode(), ISD::SRL, LSB) && 02369 !isOpcWithIntImmediate(N->getOperand(0).getNode(), ISD::SRA, LSB)) 02370 return nullptr; 02371 02372 if (LSB + Width > 32) 02373 return nullptr; 02374 02375 SDValue Reg0 = CurDAG->getRegister(0, MVT::i32); 02376 SDValue Ops[] = { N->getOperand(0).getOperand(0), 02377 CurDAG->getTargetConstant(LSB, MVT::i32), 02378 CurDAG->getTargetConstant(Width - 1, MVT::i32), 02379 getAL(CurDAG), Reg0 }; 02380 return CurDAG->SelectNodeTo(N, Opc, MVT::i32, Ops); 02381 } 02382 02383 return nullptr; 02384 } 02385 02386 /// Target-specific DAG combining for ISD::XOR. 02387 /// Target-independent combining lowers SELECT_CC nodes of the form 02388 /// select_cc setg[ge] X, 0, X, -X 02389 /// select_cc setgt X, -1, X, -X 02390 /// select_cc setl[te] X, 0, -X, X 02391 /// select_cc setlt X, 1, -X, X 02392 /// which represent Integer ABS into: 02393 /// Y = sra (X, size(X)-1); xor (add (X, Y), Y) 02394 /// ARM instruction selection detects the latter and matches it to 02395 /// ARM::ABS or ARM::t2ABS machine node. 02396 SDNode *ARMDAGToDAGISel::SelectABSOp(SDNode *N){ 02397 SDValue XORSrc0 = N->getOperand(0); 02398 SDValue XORSrc1 = N->getOperand(1); 02399 EVT VT = N->getValueType(0); 02400 02401 if (Subtarget->isThumb1Only()) 02402 return nullptr; 02403 02404 if (XORSrc0.getOpcode() != ISD::ADD || XORSrc1.getOpcode() != ISD::SRA) 02405 return nullptr; 02406 02407 SDValue ADDSrc0 = XORSrc0.getOperand(0); 02408 SDValue ADDSrc1 = XORSrc0.getOperand(1); 02409 SDValue SRASrc0 = XORSrc1.getOperand(0); 02410 SDValue SRASrc1 = XORSrc1.getOperand(1); 02411 ConstantSDNode *SRAConstant = dyn_cast<ConstantSDNode>(SRASrc1); 02412 EVT XType = SRASrc0.getValueType(); 02413 unsigned Size = XType.getSizeInBits() - 1; 02414 02415 if (ADDSrc1 == XORSrc1 && ADDSrc0 == SRASrc0 && 02416 XType.isInteger() && SRAConstant != nullptr && 02417 Size == SRAConstant->getZExtValue()) { 02418 unsigned Opcode = Subtarget->isThumb2() ? ARM::t2ABS : ARM::ABS; 02419 return CurDAG->SelectNodeTo(N, Opcode, VT, ADDSrc0); 02420 } 02421 02422 return nullptr; 02423 } 02424 02425 SDNode *ARMDAGToDAGISel::SelectConcatVector(SDNode *N) { 02426 // The only time a CONCAT_VECTORS operation can have legal types is when 02427 // two 64-bit vectors are concatenated to a 128-bit vector. 02428 EVT VT = N->getValueType(0); 02429 if (!VT.is128BitVector() || N->getNumOperands() != 2) 02430 llvm_unreachable("unexpected CONCAT_VECTORS"); 02431 return createDRegPairNode(VT, N->getOperand(0), N->getOperand(1)); 02432 } 02433 02434 SDNode *ARMDAGToDAGISel::Select(SDNode *N) { 02435 SDLoc dl(N); 02436 02437 if (N->isMachineOpcode()) { 02438 N->setNodeId(-1); 02439 return nullptr; // Already selected. 02440 } 02441 02442 switch (N->getOpcode()) { 02443 default: break; 02444 case ISD::INLINEASM: { 02445 SDNode *ResNode = SelectInlineAsm(N); 02446 if (ResNode) 02447 return ResNode; 02448 break; 02449 } 02450 case ISD::XOR: { 02451 // Select special operations if XOR node forms integer ABS pattern 02452 SDNode *ResNode = SelectABSOp(N); 02453 if (ResNode) 02454 return ResNode; 02455 // Other cases are autogenerated. 02456 break; 02457 } 02458 case ISD::Constant: { 02459 unsigned Val = cast<ConstantSDNode>(N)->getZExtValue(); 02460 bool UseCP = true; 02461 if (Subtarget->useMovt(*MF)) 02462 // Thumb2-aware targets have the MOVT instruction, so all immediates can 02463 // be done with MOV + MOVT, at worst. 02464 UseCP = false; 02465 else { 02466 if (Subtarget->isThumb()) { 02467 UseCP = (Val > 255 && // MOV 02468 ~Val > 255 && // MOV + MVN 02469 !ARM_AM::isThumbImmShiftedVal(Val) && // MOV + LSL 02470 !(Subtarget->hasV6T2Ops() && Val <= 0xffff)); // MOVW 02471 } else 02472 UseCP = (ARM_AM::getSOImmVal(Val) == -1 && // MOV 02473 ARM_AM::getSOImmVal(~Val) == -1 && // MVN 02474 !ARM_AM::isSOImmTwoPartVal(Val) && // two instrs. 02475 !(Subtarget->hasV6T2Ops() && Val <= 0xffff)); // MOVW 02476 } 02477 02478 if (UseCP) { 02479 SDValue CPIdx = 02480 CurDAG->getTargetConstantPool(ConstantInt::get( 02481 Type::getInt32Ty(*CurDAG->getContext()), Val), 02482 getTargetLowering()->getPointerTy()); 02483 02484 SDNode *ResNode; 02485 if (Subtarget->isThumb()) { 02486 SDValue Pred = getAL(CurDAG); 02487 SDValue PredReg = CurDAG->getRegister(0, MVT::i32); 02488 SDValue Ops[] = { CPIdx, Pred, PredReg, CurDAG->getEntryNode() }; 02489 ResNode = CurDAG->getMachineNode(ARM::tLDRpci, dl, MVT::i32, MVT::Other, 02490 Ops); 02491 } else { 02492 SDValue Ops[] = { 02493 CPIdx, 02494 CurDAG->getTargetConstant(0, MVT::i32), 02495 getAL(CurDAG), 02496 CurDAG->getRegister(0, MVT::i32), 02497 CurDAG->getEntryNode() 02498 }; 02499 ResNode=CurDAG->getMachineNode(ARM::LDRcp, dl, MVT::i32, MVT::Other, 02500 Ops); 02501 } 02502 ReplaceUses(SDValue(N, 0), SDValue(ResNode, 0)); 02503 return nullptr; 02504 } 02505 02506 // Other cases are autogenerated. 02507 break; 02508 } 02509 case ISD::FrameIndex: { 02510 // Selects to ADDri FI, 0 which in turn will become ADDri SP, imm. 02511 int FI = cast<FrameIndexSDNode>(N)->getIndex(); 02512 SDValue TFI = CurDAG->getTargetFrameIndex(FI, 02513 getTargetLowering()->getPointerTy()); 02514 if (Subtarget->isThumb1Only()) { 02515 SDValue Ops[] = { TFI, CurDAG->getTargetConstant(0, MVT::i32), 02516 getAL(CurDAG), CurDAG->getRegister(0, MVT::i32) }; 02517 return CurDAG->SelectNodeTo(N, ARM::tADDrSPi, MVT::i32, Ops); 02518 } else { 02519 unsigned Opc = ((Subtarget->isThumb() && Subtarget->hasThumb2()) ? 02520 ARM::t2ADDri : ARM::ADDri); 02521 SDValue Ops[] = { TFI, CurDAG->getTargetConstant(0, MVT::i32), 02522 getAL(CurDAG), CurDAG->getRegister(0, MVT::i32), 02523 CurDAG->getRegister(0, MVT::i32) }; 02524 return CurDAG->SelectNodeTo(N, Opc, MVT::i32, Ops); 02525 } 02526 } 02527 case ISD::SRL: 02528 if (SDNode *I = SelectV6T2BitfieldExtractOp(N, false)) 02529 return I; 02530 break; 02531 case ISD::SIGN_EXTEND_INREG: 02532 case ISD::SRA: 02533 if (SDNode *I = SelectV6T2BitfieldExtractOp(N, true)) 02534 return I; 02535 break; 02536 case ISD::MUL: 02537 if (Subtarget->isThumb1Only()) 02538 break; 02539 if (ConstantSDNode *C = dyn_cast<ConstantSDNode>(N->getOperand(1))) { 02540 unsigned RHSV = C->getZExtValue(); 02541 if (!RHSV) break; 02542 if (isPowerOf2_32(RHSV-1)) { // 2^n+1? 02543 unsigned ShImm = Log2_32(RHSV-1); 02544 if (ShImm >= 32) 02545 break; 02546 SDValue V = N->getOperand(0); 02547 ShImm = ARM_AM::getSORegOpc(ARM_AM::lsl, ShImm); 02548 SDValue ShImmOp = CurDAG->getTargetConstant(ShImm, MVT::i32); 02549 SDValue Reg0 = CurDAG->getRegister(0, MVT::i32); 02550 if (Subtarget->isThumb()) { 02551 SDValue Ops[] = { V, V, ShImmOp, getAL(CurDAG), Reg0, Reg0 }; 02552 return CurDAG->SelectNodeTo(N, ARM::t2ADDrs, MVT::i32, Ops); 02553 } else { 02554 SDValue Ops[] = { V, V, Reg0, ShImmOp, getAL(CurDAG), Reg0, Reg0 }; 02555 return CurDAG->SelectNodeTo(N, ARM::ADDrsi, MVT::i32, Ops); 02556 } 02557 } 02558 if (isPowerOf2_32(RHSV+1)) { // 2^n-1? 02559 unsigned ShImm = Log2_32(RHSV+1); 02560 if (ShImm >= 32) 02561 break; 02562 SDValue V = N->getOperand(0); 02563 ShImm = ARM_AM::getSORegOpc(ARM_AM::lsl, ShImm); 02564 SDValue ShImmOp = CurDAG->getTargetConstant(ShImm, MVT::i32); 02565 SDValue Reg0 = CurDAG->getRegister(0, MVT::i32); 02566 if (Subtarget->isThumb()) { 02567 SDValue Ops[] = { V, V, ShImmOp, getAL(CurDAG), Reg0, Reg0 }; 02568 return CurDAG->SelectNodeTo(N, ARM::t2RSBrs, MVT::i32, Ops); 02569 } else { 02570 SDValue Ops[] = { V, V, Reg0, ShImmOp, getAL(CurDAG), Reg0, Reg0 }; 02571 return CurDAG->SelectNodeTo(N, ARM::RSBrsi, MVT::i32, Ops); 02572 } 02573 } 02574 } 02575 break; 02576 case ISD::AND: { 02577 // Check for unsigned bitfield extract 02578 if (SDNode *I = SelectV6T2BitfieldExtractOp(N, false)) 02579 return I; 02580 02581 // (and (or x, c2), c1) and top 16-bits of c1 and c2 match, lower 16-bits 02582 // of c1 are 0xffff, and lower 16-bit of c2 are 0. That is, the top 16-bits 02583 // are entirely contributed by c2 and lower 16-bits are entirely contributed 02584 // by x. That's equal to (or (and x, 0xffff), (and c1, 0xffff0000)). 02585 // Select it to: "movt x, ((c1 & 0xffff) >> 16) 02586 EVT VT = N->getValueType(0); 02587 if (VT != MVT::i32) 02588 break; 02589 unsigned Opc = (Subtarget->isThumb() && Subtarget->hasThumb2()) 02590 ? ARM::t2MOVTi16 02591 : (Subtarget->hasV6T2Ops() ? ARM::MOVTi16 : 0); 02592 if (!Opc) 02593 break; 02594 SDValue N0 = N->getOperand(0), N1 = N->getOperand(1); 02595 ConstantSDNode *N1C = dyn_cast<ConstantSDNode>(N1); 02596 if (!N1C) 02597 break; 02598 if (N0.getOpcode() == ISD::OR && N0.getNode()->hasOneUse()) { 02599 SDValue N2 = N0.getOperand(1); 02600 ConstantSDNode *N2C = dyn_cast<ConstantSDNode>(N2); 02601 if (!N2C) 02602 break; 02603 unsigned N1CVal = N1C->getZExtValue(); 02604 unsigned N2CVal = N2C->getZExtValue(); 02605 if ((N1CVal & 0xffff0000U) == (N2CVal & 0xffff0000U) && 02606 (N1CVal & 0xffffU) == 0xffffU && 02607 (N2CVal & 0xffffU) == 0x0U) { 02608 SDValue Imm16 = CurDAG->getTargetConstant((N2CVal & 0xFFFF0000U) >> 16, 02609 MVT::i32); 02610 SDValue Ops[] = { N0.getOperand(0), Imm16, 02611 getAL(CurDAG), CurDAG->getRegister(0, MVT::i32) }; 02612 return CurDAG->getMachineNode(Opc, dl, VT, Ops); 02613 } 02614 } 02615 break; 02616 } 02617 case ARMISD::VMOVRRD: 02618 return CurDAG->getMachineNode(ARM::VMOVRRD, dl, MVT::i32, MVT::i32, 02619 N->getOperand(0), getAL(CurDAG), 02620 CurDAG->getRegister(0, MVT::i32)); 02621 case ISD::UMUL_LOHI: { 02622 if (Subtarget->isThumb1Only()) 02623 break; 02624 if (Subtarget->isThumb()) { 02625 SDValue Ops[] = { N->getOperand(0), N->getOperand(1), 02626 getAL(CurDAG), CurDAG->getRegister(0, MVT::i32) }; 02627 return CurDAG->getMachineNode(ARM::t2UMULL, dl, MVT::i32, MVT::i32, Ops); 02628 } else { 02629 SDValue Ops[] = { N->getOperand(0), N->getOperand(1), 02630 getAL(CurDAG), CurDAG->getRegister(0, MVT::i32), 02631 CurDAG->getRegister(0, MVT::i32) }; 02632 return CurDAG->getMachineNode(Subtarget->hasV6Ops() ? 02633 ARM::UMULL : ARM::UMULLv5, 02634 dl, MVT::i32, MVT::i32, Ops); 02635 } 02636 } 02637 case ISD::SMUL_LOHI: { 02638 if (Subtarget->isThumb1Only()) 02639 break; 02640 if (Subtarget->isThumb()) { 02641 SDValue Ops[] = { N->getOperand(0), N->getOperand(1), 02642 getAL(CurDAG), CurDAG->getRegister(0, MVT::i32) }; 02643 return CurDAG->getMachineNode(ARM::t2SMULL, dl, MVT::i32, MVT::i32, Ops); 02644 } else { 02645 SDValue Ops[] = { N->getOperand(0), N->getOperand(1), 02646 getAL(CurDAG), CurDAG->getRegister(0, MVT::i32), 02647 CurDAG->getRegister(0, MVT::i32) }; 02648 return CurDAG->getMachineNode(Subtarget->hasV6Ops() ? 02649 ARM::SMULL : ARM::SMULLv5, 02650 dl, MVT::i32, MVT::i32, Ops); 02651 } 02652 } 02653 case ARMISD::UMLAL:{ 02654 if (Subtarget->isThumb()) { 02655 SDValue Ops[] = { N->getOperand(0), N->getOperand(1), N->getOperand(2), 02656 N->getOperand(3), getAL(CurDAG), 02657 CurDAG->getRegister(0, MVT::i32)}; 02658 return CurDAG->getMachineNode(ARM::t2UMLAL, dl, MVT::i32, MVT::i32, Ops); 02659 }else{ 02660 SDValue Ops[] = { N->getOperand(0), N->getOperand(1), N->getOperand(2), 02661 N->getOperand(3), getAL(CurDAG), 02662 CurDAG->getRegister(0, MVT::i32), 02663 CurDAG->getRegister(0, MVT::i32) }; 02664 return CurDAG->getMachineNode(Subtarget->hasV6Ops() ? 02665 ARM::UMLAL : ARM::UMLALv5, 02666 dl, MVT::i32, MVT::i32, Ops); 02667 } 02668 } 02669 case ARMISD::SMLAL:{ 02670 if (Subtarget->isThumb()) { 02671 SDValue Ops[] = { N->getOperand(0), N->getOperand(1), N->getOperand(2), 02672 N->getOperand(3), getAL(CurDAG), 02673 CurDAG->getRegister(0, MVT::i32)}; 02674 return CurDAG->getMachineNode(ARM::t2SMLAL, dl, MVT::i32, MVT::i32, Ops); 02675 }else{ 02676 SDValue Ops[] = { N->getOperand(0), N->getOperand(1), N->getOperand(2), 02677 N->getOperand(3), getAL(CurDAG), 02678 CurDAG->getRegister(0, MVT::i32), 02679 CurDAG->getRegister(0, MVT::i32) }; 02680 return CurDAG->getMachineNode(Subtarget->hasV6Ops() ? 02681 ARM::SMLAL : ARM::SMLALv5, 02682 dl, MVT::i32, MVT::i32, Ops); 02683 } 02684 } 02685 case ISD::LOAD: { 02686 SDNode *ResNode = nullptr; 02687 if (Subtarget->isThumb() && Subtarget->hasThumb2()) 02688 ResNode = SelectT2IndexedLoad(N); 02689 else 02690 ResNode = SelectARMIndexedLoad(N); 02691 if (ResNode) 02692 return ResNode; 02693 // Other cases are autogenerated. 02694 break; 02695 } 02696 case ARMISD::BRCOND: { 02697 // Pattern: (ARMbrcond:void (bb:Other):$dst, (imm:i32):$cc) 02698 // Emits: (Bcc:void (bb:Other):$dst, (imm:i32):$cc) 02699 // Pattern complexity = 6 cost = 1 size = 0 02700 02701 // Pattern: (ARMbrcond:void (bb:Other):$dst, (imm:i32):$cc) 02702 // Emits: (tBcc:void (bb:Other):$dst, (imm:i32):$cc) 02703 // Pattern complexity = 6 cost = 1 size = 0 02704 02705 // Pattern: (ARMbrcond:void (bb:Other):$dst, (imm:i32):$cc) 02706 // Emits: (t2Bcc:void (bb:Other):$dst, (imm:i32):$cc) 02707 // Pattern complexity = 6 cost = 1 size = 0 02708 02709 unsigned Opc = Subtarget->isThumb() ? 02710 ((Subtarget->hasThumb2()) ? ARM::t2Bcc : ARM::tBcc) : ARM::Bcc; 02711 SDValue Chain = N->getOperand(0); 02712 SDValue N1 = N->getOperand(1); 02713 SDValue N2 = N->getOperand(2); 02714 SDValue N3 = N->getOperand(3); 02715 SDValue InFlag = N->getOperand(4); 02716 assert(N1.getOpcode() == ISD::BasicBlock); 02717 assert(N2.getOpcode() == ISD::Constant); 02718 assert(N3.getOpcode() == ISD::Register); 02719 02720 SDValue Tmp2 = CurDAG->getTargetConstant(((unsigned) 02721 cast<ConstantSDNode>(N2)->getZExtValue()), 02722 MVT::i32); 02723 SDValue Ops[] = { N1, Tmp2, N3, Chain, InFlag }; 02724 SDNode *ResNode = CurDAG->getMachineNode(Opc, dl, MVT::Other, 02725 MVT::Glue, Ops); 02726 Chain = SDValue(ResNode, 0); 02727 if (N->getNumValues() == 2) { 02728 InFlag = SDValue(ResNode, 1); 02729 ReplaceUses(SDValue(N, 1), InFlag); 02730 } 02731 ReplaceUses(SDValue(N, 0), 02732 SDValue(Chain.getNode(), Chain.getResNo())); 02733 return nullptr; 02734 } 02735 case ARMISD::VZIP: { 02736 unsigned Opc = 0; 02737 EVT VT = N->getValueType(0); 02738 switch (VT.getSimpleVT().SimpleTy) { 02739 default: return nullptr; 02740 case MVT::v8i8: Opc = ARM::VZIPd8; break; 02741 case MVT::v4i16: Opc = ARM::VZIPd16; break; 02742 case MVT::v2f32: 02743 // vzip.32 Dd, Dm is a pseudo-instruction expanded to vtrn.32 Dd, Dm. 02744 case MVT::v2i32: Opc = ARM::VTRNd32; break; 02745 case MVT::v16i8: Opc = ARM::VZIPq8; break; 02746 case MVT::v8i16: Opc = ARM::VZIPq16; break; 02747 case MVT::v4f32: 02748 case MVT::v4i32: Opc = ARM::VZIPq32; break; 02749 } 02750 SDValue Pred = getAL(CurDAG); 02751 SDValue PredReg = CurDAG->getRegister(0, MVT::i32); 02752 SDValue Ops[] = { N->getOperand(0), N->getOperand(1), Pred, PredReg }; 02753 return CurDAG->getMachineNode(Opc, dl, VT, VT, Ops); 02754 } 02755 case ARMISD::VUZP: { 02756 unsigned Opc = 0; 02757 EVT VT = N->getValueType(0); 02758 switch (VT.getSimpleVT().SimpleTy) { 02759 default: return nullptr; 02760 case MVT::v8i8: Opc = ARM::VUZPd8; break; 02761 case MVT::v4i16: Opc = ARM::VUZPd16; break; 02762 case MVT::v2f32: 02763 // vuzp.32 Dd, Dm is a pseudo-instruction expanded to vtrn.32 Dd, Dm. 02764 case MVT::v2i32: Opc = ARM::VTRNd32; break; 02765 case MVT::v16i8: Opc = ARM::VUZPq8; break; 02766 case MVT::v8i16: Opc = ARM::VUZPq16; break; 02767 case MVT::v4f32: 02768 case MVT::v4i32: Opc = ARM::VUZPq32; break; 02769 } 02770 SDValue Pred = getAL(CurDAG); 02771 SDValue PredReg = CurDAG->getRegister(0, MVT::i32); 02772 SDValue Ops[] = { N->getOperand(0), N->getOperand(1), Pred, PredReg }; 02773 return CurDAG->getMachineNode(Opc, dl, VT, VT, Ops); 02774 } 02775 case ARMISD::VTRN: { 02776 unsigned Opc = 0; 02777 EVT VT = N->getValueType(0); 02778 switch (VT.getSimpleVT().SimpleTy) { 02779 default: return nullptr; 02780 case MVT::v8i8: Opc = ARM::VTRNd8; break; 02781 case MVT::v4i16: Opc = ARM::VTRNd16; break; 02782 case MVT::v2f32: 02783 case MVT::v2i32: Opc = ARM::VTRNd32; break; 02784 case MVT::v16i8: Opc = ARM::VTRNq8; break; 02785 case MVT::v8i16: Opc = ARM::VTRNq16; break; 02786 case MVT::v4f32: 02787 case MVT::v4i32: Opc = ARM::VTRNq32; break; 02788 } 02789 SDValue Pred = getAL(CurDAG); 02790 SDValue PredReg = CurDAG->getRegister(0, MVT::i32); 02791 SDValue Ops[] = { N->getOperand(0), N->getOperand(1), Pred, PredReg }; 02792 return CurDAG->getMachineNode(Opc, dl, VT, VT, Ops); 02793 } 02794 case ARMISD::BUILD_VECTOR: { 02795 EVT VecVT = N->getValueType(0); 02796 EVT EltVT = VecVT.getVectorElementType(); 02797 unsigned NumElts = VecVT.getVectorNumElements(); 02798 if (EltVT == MVT::f64) { 02799 assert(NumElts == 2 && "unexpected type for BUILD_VECTOR"); 02800 return createDRegPairNode(VecVT, N->getOperand(0), N->getOperand(1)); 02801 } 02802 assert(EltVT == MVT::f32 && "unexpected type for BUILD_VECTOR"); 02803 if (NumElts == 2) 02804 return createSRegPairNode(VecVT, N->getOperand(0), N->getOperand(1)); 02805 assert(NumElts == 4 && "unexpected type for BUILD_VECTOR"); 02806 return createQuadSRegsNode(VecVT, N->getOperand(0), N->getOperand(1), 02807 N->getOperand(2), N->getOperand(3)); 02808 } 02809 02810 case ARMISD::VLD2DUP: { 02811 static const uint16_t Opcodes[] = { ARM::VLD2DUPd8, ARM::VLD2DUPd16, 02812 ARM::VLD2DUPd32 }; 02813 return SelectVLDDup(N, false, 2, Opcodes); 02814 } 02815 02816 case ARMISD::VLD3DUP: { 02817 static const uint16_t Opcodes[] = { ARM::VLD3DUPd8Pseudo, 02818 ARM::VLD3DUPd16Pseudo, 02819 ARM::VLD3DUPd32Pseudo }; 02820 return SelectVLDDup(N, false, 3, Opcodes); 02821 } 02822 02823 case ARMISD::VLD4DUP: { 02824 static const uint16_t Opcodes[] = { ARM::VLD4DUPd8Pseudo, 02825 ARM::VLD4DUPd16Pseudo, 02826 ARM::VLD4DUPd32Pseudo }; 02827 return SelectVLDDup(N, false, 4, Opcodes); 02828 } 02829 02830 case ARMISD::VLD2DUP_UPD: { 02831 static const uint16_t Opcodes[] = { ARM::VLD2DUPd8wb_fixed, 02832 ARM::VLD2DUPd16wb_fixed, 02833 ARM::VLD2DUPd32wb_fixed }; 02834 return SelectVLDDup(N, true, 2, Opcodes); 02835 } 02836 02837 case ARMISD::VLD3DUP_UPD: { 02838 static const uint16_t Opcodes[] = { ARM::VLD3DUPd8Pseudo_UPD, 02839 ARM::VLD3DUPd16Pseudo_UPD, 02840 ARM::VLD3DUPd32Pseudo_UPD }; 02841 return SelectVLDDup(N, true, 3, Opcodes); 02842 } 02843 02844 case ARMISD::VLD4DUP_UPD: { 02845 static const uint16_t Opcodes[] = { ARM::VLD4DUPd8Pseudo_UPD, 02846 ARM::VLD4DUPd16Pseudo_UPD, 02847 ARM::VLD4DUPd32Pseudo_UPD }; 02848 return SelectVLDDup(N, true, 4, Opcodes); 02849 } 02850 02851 case ARMISD::VLD1_UPD: { 02852 static const uint16_t DOpcodes[] = { ARM::VLD1d8wb_fixed, 02853 ARM::VLD1d16wb_fixed, 02854 ARM::VLD1d32wb_fixed, 02855 ARM::VLD1d64wb_fixed }; 02856 static const uint16_t QOpcodes[] = { ARM::VLD1q8wb_fixed, 02857 ARM::VLD1q16wb_fixed, 02858 ARM::VLD1q32wb_fixed, 02859 ARM::VLD1q64wb_fixed }; 02860 return SelectVLD(N, true, 1, DOpcodes, QOpcodes, nullptr); 02861 } 02862 02863 case ARMISD::VLD2_UPD: { 02864 static const uint16_t DOpcodes[] = { ARM::VLD2d8wb_fixed, 02865 ARM::VLD2d16wb_fixed, 02866 ARM::VLD2d32wb_fixed, 02867 ARM::VLD1q64wb_fixed}; 02868 static const uint16_t QOpcodes[] = { ARM::VLD2q8PseudoWB_fixed, 02869 ARM::VLD2q16PseudoWB_fixed, 02870 ARM::VLD2q32PseudoWB_fixed }; 02871 return SelectVLD(N, true, 2, DOpcodes, QOpcodes, nullptr); 02872 } 02873 02874 case ARMISD::VLD3_UPD: { 02875 static const uint16_t DOpcodes[] = { ARM::VLD3d8Pseudo_UPD, 02876 ARM::VLD3d16Pseudo_UPD, 02877 ARM::VLD3d32Pseudo_UPD, 02878 ARM::VLD1d64TPseudoWB_fixed}; 02879 static const uint16_t QOpcodes0[] = { ARM::VLD3q8Pseudo_UPD, 02880 ARM::VLD3q16Pseudo_UPD, 02881 ARM::VLD3q32Pseudo_UPD }; 02882 static const uint16_t QOpcodes1[] = { ARM::VLD3q8oddPseudo_UPD, 02883 ARM::VLD3q16oddPseudo_UPD, 02884 ARM::VLD3q32oddPseudo_UPD }; 02885 return SelectVLD(N, true, 3, DOpcodes, QOpcodes0, QOpcodes1); 02886 } 02887 02888 case ARMISD::VLD4_UPD: { 02889 static const uint16_t DOpcodes[] = { ARM::VLD4d8Pseudo_UPD, 02890 ARM::VLD4d16Pseudo_UPD, 02891 ARM::VLD4d32Pseudo_UPD, 02892 ARM::VLD1d64QPseudoWB_fixed}; 02893 static const uint16_t QOpcodes0[] = { ARM::VLD4q8Pseudo_UPD, 02894 ARM::VLD4q16Pseudo_UPD, 02895 ARM::VLD4q32Pseudo_UPD }; 02896 static const uint16_t QOpcodes1[] = { ARM::VLD4q8oddPseudo_UPD, 02897 ARM::VLD4q16oddPseudo_UPD, 02898 ARM::VLD4q32oddPseudo_UPD }; 02899 return SelectVLD(N, true, 4, DOpcodes, QOpcodes0, QOpcodes1); 02900 } 02901 02902 case ARMISD::VLD2LN_UPD: { 02903 static const uint16_t DOpcodes[] = { ARM::VLD2LNd8Pseudo_UPD, 02904 ARM::VLD2LNd16Pseudo_UPD, 02905 ARM::VLD2LNd32Pseudo_UPD }; 02906 static const uint16_t QOpcodes[] = { ARM::VLD2LNq16Pseudo_UPD, 02907 ARM::VLD2LNq32Pseudo_UPD }; 02908 return SelectVLDSTLane(N, true, true, 2, DOpcodes, QOpcodes); 02909 } 02910 02911 case ARMISD::VLD3LN_UPD: { 02912 static const uint16_t DOpcodes[] = { ARM::VLD3LNd8Pseudo_UPD, 02913 ARM::VLD3LNd16Pseudo_UPD, 02914 ARM::VLD3LNd32Pseudo_UPD }; 02915 static const uint16_t QOpcodes[] = { ARM::VLD3LNq16Pseudo_UPD, 02916 ARM::VLD3LNq32Pseudo_UPD }; 02917 return SelectVLDSTLane(N, true, true, 3, DOpcodes, QOpcodes); 02918 } 02919 02920 case ARMISD::VLD4LN_UPD: { 02921 static const uint16_t DOpcodes[] = { ARM::VLD4LNd8Pseudo_UPD, 02922 ARM::VLD4LNd16Pseudo_UPD, 02923 ARM::VLD4LNd32Pseudo_UPD }; 02924 static const uint16_t QOpcodes[] = { ARM::VLD4LNq16Pseudo_UPD, 02925 ARM::VLD4LNq32Pseudo_UPD }; 02926 return SelectVLDSTLane(N, true, true, 4, DOpcodes, QOpcodes); 02927 } 02928 02929 case ARMISD::VST1_UPD: { 02930 static const uint16_t DOpcodes[] = { ARM::VST1d8wb_fixed, 02931 ARM::VST1d16wb_fixed, 02932 ARM::VST1d32wb_fixed, 02933 ARM::VST1d64wb_fixed }; 02934 static const uint16_t QOpcodes[] = { ARM::VST1q8wb_fixed, 02935 ARM::VST1q16wb_fixed, 02936 ARM::VST1q32wb_fixed, 02937 ARM::VST1q64wb_fixed }; 02938 return SelectVST(N, true, 1, DOpcodes, QOpcodes, nullptr); 02939 } 02940 02941 case ARMISD::VST2_UPD: { 02942 static const uint16_t DOpcodes[] = { ARM::VST2d8wb_fixed, 02943 ARM::VST2d16wb_fixed, 02944 ARM::VST2d32wb_fixed, 02945 ARM::VST1q64wb_fixed}; 02946 static const uint16_t QOpcodes[] = { ARM::VST2q8PseudoWB_fixed, 02947 ARM::VST2q16PseudoWB_fixed, 02948 ARM::VST2q32PseudoWB_fixed }; 02949 return SelectVST(N, true, 2, DOpcodes, QOpcodes, nullptr); 02950 } 02951 02952 case ARMISD::VST3_UPD: { 02953 static const uint16_t DOpcodes[] = { ARM::VST3d8Pseudo_UPD, 02954 ARM::VST3d16Pseudo_UPD, 02955 ARM::VST3d32Pseudo_UPD, 02956 ARM::VST1d64TPseudoWB_fixed}; 02957 static const uint16_t QOpcodes0[] = { ARM::VST3q8Pseudo_UPD, 02958 ARM::VST3q16Pseudo_UPD, 02959 ARM::VST3q32Pseudo_UPD }; 02960 static const uint16_t QOpcodes1[] = { ARM::VST3q8oddPseudo_UPD, 02961 ARM::VST3q16oddPseudo_UPD, 02962 ARM::VST3q32oddPseudo_UPD }; 02963 return SelectVST(N, true, 3, DOpcodes, QOpcodes0, QOpcodes1); 02964 } 02965 02966 case ARMISD::VST4_UPD: { 02967 static const uint16_t DOpcodes[] = { ARM::VST4d8Pseudo_UPD, 02968 ARM::VST4d16Pseudo_UPD, 02969 ARM::VST4d32Pseudo_UPD, 02970 ARM::VST1d64QPseudoWB_fixed}; 02971 static const uint16_t QOpcodes0[] = { ARM::VST4q8Pseudo_UPD, 02972 ARM::VST4q16Pseudo_UPD, 02973 ARM::VST4q32Pseudo_UPD }; 02974 static const uint16_t QOpcodes1[] = { ARM::VST4q8oddPseudo_UPD, 02975 ARM::VST4q16oddPseudo_UPD, 02976 ARM::VST4q32oddPseudo_UPD }; 02977 return SelectVST(N, true, 4, DOpcodes, QOpcodes0, QOpcodes1); 02978 } 02979 02980 case ARMISD::VST2LN_UPD: { 02981 static const uint16_t DOpcodes[] = { ARM::VST2LNd8Pseudo_UPD, 02982 ARM::VST2LNd16Pseudo_UPD, 02983 ARM::VST2LNd32Pseudo_UPD }; 02984 static const uint16_t QOpcodes[] = { ARM::VST2LNq16Pseudo_UPD, 02985 ARM::VST2LNq32Pseudo_UPD }; 02986 return SelectVLDSTLane(N, false, true, 2, DOpcodes, QOpcodes); 02987 } 02988 02989 case ARMISD::VST3LN_UPD: { 02990 static const uint16_t DOpcodes[] = { ARM::VST3LNd8Pseudo_UPD, 02991 ARM::VST3LNd16Pseudo_UPD, 02992 ARM::VST3LNd32Pseudo_UPD }; 02993 static const uint16_t QOpcodes[] = { ARM::VST3LNq16Pseudo_UPD, 02994 ARM::VST3LNq32Pseudo_UPD }; 02995 return SelectVLDSTLane(N, false, true, 3, DOpcodes, QOpcodes); 02996 } 02997 02998 case ARMISD::VST4LN_UPD: { 02999 static const uint16_t DOpcodes[] = { ARM::VST4LNd8Pseudo_UPD, 03000 ARM::VST4LNd16Pseudo_UPD, 03001 ARM::VST4LNd32Pseudo_UPD }; 03002 static const uint16_t QOpcodes[] = { ARM::VST4LNq16Pseudo_UPD, 03003 ARM::VST4LNq32Pseudo_UPD }; 03004 return SelectVLDSTLane(N, false, true, 4, DOpcodes, QOpcodes); 03005 } 03006 03007 case ISD::INTRINSIC_VOID: 03008 case ISD::INTRINSIC_W_CHAIN: { 03009 unsigned IntNo = cast<ConstantSDNode>(N->getOperand(1))->getZExtValue(); 03010 switch (IntNo) { 03011 default: 03012 break; 03013 03014 case Intrinsic::arm_ldaexd: 03015 case Intrinsic::arm_ldrexd: { 03016 SDLoc dl(N); 03017 SDValue Chain = N->getOperand(0); 03018 SDValue MemAddr = N->getOperand(2); 03019 bool isThumb = Subtarget->isThumb() && Subtarget->hasThumb2(); 03020 03021 bool IsAcquire = IntNo == Intrinsic::arm_ldaexd; 03022 unsigned NewOpc = isThumb ? (IsAcquire ? ARM::t2LDAEXD : ARM::t2LDREXD) 03023 : (IsAcquire ? ARM::LDAEXD : ARM::LDREXD); 03024 03025 // arm_ldrexd returns a i64 value in {i32, i32} 03026 std::vector<EVT> ResTys; 03027 if (isThumb) { 03028 ResTys.push_back(MVT::i32); 03029 ResTys.push_back(MVT::i32); 03030 } else 03031 ResTys.push_back(MVT::Untyped); 03032 ResTys.push_back(MVT::Other); 03033 03034 // Place arguments in the right order. 03035 SmallVector<SDValue, 7> Ops; 03036 Ops.push_back(MemAddr); 03037 Ops.push_back(getAL(CurDAG)); 03038 Ops.push_back(CurDAG->getRegister(0, MVT::i32)); 03039 Ops.push_back(Chain); 03040 SDNode *Ld = CurDAG->getMachineNode(NewOpc, dl, ResTys, Ops); 03041 // Transfer memoperands. 03042 MachineSDNode::mmo_iterator MemOp = MF->allocateMemRefsArray(1); 03043 MemOp[0] = cast<MemIntrinsicSDNode>(N)->getMemOperand(); 03044 cast<MachineSDNode>(Ld)->setMemRefs(MemOp, MemOp + 1); 03045 03046 // Remap uses. 03047 SDValue OutChain = isThumb ? SDValue(Ld, 2) : SDValue(Ld, 1); 03048 if (!SDValue(N, 0).use_empty()) { 03049 SDValue Result; 03050 if (isThumb) 03051 Result = SDValue(Ld, 0); 03052 else { 03053 SDValue SubRegIdx = CurDAG->getTargetConstant(ARM::gsub_0, MVT::i32); 03054 SDNode *ResNode = CurDAG->getMachineNode(TargetOpcode::EXTRACT_SUBREG, 03055 dl, MVT::i32, SDValue(Ld, 0), SubRegIdx); 03056 Result = SDValue(ResNode,0); 03057 } 03058 ReplaceUses(SDValue(N, 0), Result); 03059 } 03060 if (!SDValue(N, 1).use_empty()) { 03061 SDValue Result; 03062 if (isThumb) 03063 Result = SDValue(Ld, 1); 03064 else { 03065 SDValue SubRegIdx = CurDAG->getTargetConstant(ARM::gsub_1, MVT::i32); 03066 SDNode *ResNode = CurDAG->getMachineNode(TargetOpcode::EXTRACT_SUBREG, 03067 dl, MVT::i32, SDValue(Ld, 0), SubRegIdx); 03068 Result = SDValue(ResNode,0); 03069 } 03070 ReplaceUses(SDValue(N, 1), Result); 03071 } 03072 ReplaceUses(SDValue(N, 2), OutChain); 03073 return nullptr; 03074 } 03075 case Intrinsic::arm_stlexd: 03076 case Intrinsic::arm_strexd: { 03077 SDLoc dl(N); 03078 SDValue Chain = N->getOperand(0); 03079 SDValue Val0 = N->getOperand(2); 03080 SDValue Val1 = N->getOperand(3); 03081 SDValue MemAddr = N->getOperand(4); 03082 03083 // Store exclusive double return a i32 value which is the return status 03084 // of the issued store. 03085 EVT ResTys[] = { MVT::i32, MVT::Other }; 03086 03087 bool isThumb = Subtarget->isThumb() && Subtarget->hasThumb2(); 03088 // Place arguments in the right order. 03089 SmallVector<SDValue, 7> Ops; 03090 if (isThumb) { 03091 Ops.push_back(Val0); 03092 Ops.push_back(Val1); 03093 } else 03094 // arm_strexd uses GPRPair. 03095 Ops.push_back(SDValue(createGPRPairNode(MVT::Untyped, Val0, Val1), 0)); 03096 Ops.push_back(MemAddr); 03097 Ops.push_back(getAL(CurDAG)); 03098 Ops.push_back(CurDAG->getRegister(0, MVT::i32)); 03099 Ops.push_back(Chain); 03100 03101 bool IsRelease = IntNo == Intrinsic::arm_stlexd; 03102 unsigned NewOpc = isThumb ? (IsRelease ? ARM::t2STLEXD : ARM::t2STREXD) 03103 : (IsRelease ? ARM::STLEXD : ARM::STREXD); 03104 03105 SDNode *St = CurDAG->getMachineNode(NewOpc, dl, ResTys, Ops); 03106 // Transfer memoperands. 03107 MachineSDNode::mmo_iterator MemOp = MF->allocateMemRefsArray(1); 03108 MemOp[0] = cast<MemIntrinsicSDNode>(N)->getMemOperand(); 03109 cast<MachineSDNode>(St)->setMemRefs(MemOp, MemOp + 1); 03110 03111 return St; 03112 } 03113 03114 case Intrinsic::arm_neon_vld1: { 03115 static const uint16_t DOpcodes[] = { ARM::VLD1d8, ARM::VLD1d16, 03116 ARM::VLD1d32, ARM::VLD1d64 }; 03117 static const uint16_t QOpcodes[] = { ARM::VLD1q8, ARM::VLD1q16, 03118 ARM::VLD1q32, ARM::VLD1q64}; 03119 return SelectVLD(N, false, 1, DOpcodes, QOpcodes, nullptr); 03120 } 03121 03122 case Intrinsic::arm_neon_vld2: { 03123 static const uint16_t DOpcodes[] = { ARM::VLD2d8, ARM::VLD2d16, 03124 ARM::VLD2d32, ARM::VLD1q64 }; 03125 static const uint16_t QOpcodes[] = { ARM::VLD2q8Pseudo, ARM::VLD2q16Pseudo, 03126 ARM::VLD2q32Pseudo }; 03127 return SelectVLD(N, false, 2, DOpcodes, QOpcodes, nullptr); 03128 } 03129 03130 case Intrinsic::arm_neon_vld3: { 03131 static const uint16_t DOpcodes[] = { ARM::VLD3d8Pseudo, 03132 ARM::VLD3d16Pseudo, 03133 ARM::VLD3d32Pseudo, 03134 ARM::VLD1d64TPseudo }; 03135 static const uint16_t QOpcodes0[] = { ARM::VLD3q8Pseudo_UPD, 03136 ARM::VLD3q16Pseudo_UPD, 03137 ARM::VLD3q32Pseudo_UPD }; 03138 static const uint16_t QOpcodes1[] = { ARM::VLD3q8oddPseudo, 03139 ARM::VLD3q16oddPseudo, 03140 ARM::VLD3q32oddPseudo }; 03141 return SelectVLD(N, false, 3, DOpcodes, QOpcodes0, QOpcodes1); 03142 } 03143 03144 case Intrinsic::arm_neon_vld4: { 03145 static const uint16_t DOpcodes[] = { ARM::VLD4d8Pseudo, 03146 ARM::VLD4d16Pseudo, 03147 ARM::VLD4d32Pseudo, 03148 ARM::VLD1d64QPseudo }; 03149 static const uint16_t QOpcodes0[] = { ARM::VLD4q8Pseudo_UPD, 03150 ARM::VLD4q16Pseudo_UPD, 03151 ARM::VLD4q32Pseudo_UPD }; 03152 static const uint16_t QOpcodes1[] = { ARM::VLD4q8oddPseudo, 03153 ARM::VLD4q16oddPseudo, 03154 ARM::VLD4q32oddPseudo }; 03155 return SelectVLD(N, false, 4, DOpcodes, QOpcodes0, QOpcodes1); 03156 } 03157 03158 case Intrinsic::arm_neon_vld2lane: { 03159 static const uint16_t DOpcodes[] = { ARM::VLD2LNd8Pseudo, 03160 ARM::VLD2LNd16Pseudo, 03161 ARM::VLD2LNd32Pseudo }; 03162 static const uint16_t QOpcodes[] = { ARM::VLD2LNq16Pseudo, 03163 ARM::VLD2LNq32Pseudo }; 03164 return SelectVLDSTLane(N, true, false, 2, DOpcodes, QOpcodes); 03165 } 03166 03167 case Intrinsic::arm_neon_vld3lane: { 03168 static const uint16_t DOpcodes[] = { ARM::VLD3LNd8Pseudo, 03169 ARM::VLD3LNd16Pseudo, 03170 ARM::VLD3LNd32Pseudo }; 03171 static const uint16_t QOpcodes[] = { ARM::VLD3LNq16Pseudo, 03172 ARM::VLD3LNq32Pseudo }; 03173 return SelectVLDSTLane(N, true, false, 3, DOpcodes, QOpcodes); 03174 } 03175 03176 case Intrinsic::arm_neon_vld4lane: { 03177 static const uint16_t DOpcodes[] = { ARM::VLD4LNd8Pseudo, 03178 ARM::VLD4LNd16Pseudo, 03179 ARM::VLD4LNd32Pseudo }; 03180 static const uint16_t QOpcodes[] = { ARM::VLD4LNq16Pseudo, 03181 ARM::VLD4LNq32Pseudo }; 03182 return SelectVLDSTLane(N, true, false, 4, DOpcodes, QOpcodes); 03183 } 03184 03185 case Intrinsic::arm_neon_vst1: { 03186 static const uint16_t DOpcodes[] = { ARM::VST1d8, ARM::VST1d16, 03187 ARM::VST1d32, ARM::VST1d64 }; 03188 static const uint16_t QOpcodes[] = { ARM::VST1q8, ARM::VST1q16, 03189 ARM::VST1q32, ARM::VST1q64 }; 03190 return SelectVST(N, false, 1, DOpcodes, QOpcodes, nullptr); 03191 } 03192 03193 case Intrinsic::arm_neon_vst2: { 03194 static const uint16_t DOpcodes[] = { ARM::VST2d8, ARM::VST2d16, 03195 ARM::VST2d32, ARM::VST1q64 }; 03196 static uint16_t QOpcodes[] = { ARM::VST2q8Pseudo, ARM::VST2q16Pseudo, 03197 ARM::VST2q32Pseudo }; 03198 return SelectVST(N, false, 2, DOpcodes, QOpcodes, nullptr); 03199 } 03200 03201 case Intrinsic::arm_neon_vst3: { 03202 static const uint16_t DOpcodes[] = { ARM::VST3d8Pseudo, 03203 ARM::VST3d16Pseudo, 03204 ARM::VST3d32Pseudo, 03205 ARM::VST1d64TPseudo }; 03206 static const uint16_t QOpcodes0[] = { ARM::VST3q8Pseudo_UPD, 03207 ARM::VST3q16Pseudo_UPD, 03208 ARM::VST3q32Pseudo_UPD }; 03209 static const uint16_t QOpcodes1[] = { ARM::VST3q8oddPseudo, 03210 ARM::VST3q16oddPseudo, 03211 ARM::VST3q32oddPseudo }; 03212 return SelectVST(N, false, 3, DOpcodes, QOpcodes0, QOpcodes1); 03213 } 03214 03215 case Intrinsic::arm_neon_vst4: { 03216 static const uint16_t DOpcodes[] = { ARM::VST4d8Pseudo, 03217 ARM::VST4d16Pseudo, 03218 ARM::VST4d32Pseudo, 03219 ARM::VST1d64QPseudo }; 03220 static const uint16_t QOpcodes0[] = { ARM::VST4q8Pseudo_UPD, 03221 ARM::VST4q16Pseudo_UPD, 03222 ARM::VST4q32Pseudo_UPD }; 03223 static const uint16_t QOpcodes1[] = { ARM::VST4q8oddPseudo, 03224 ARM::VST4q16oddPseudo, 03225 ARM::VST4q32oddPseudo }; 03226 return SelectVST(N, false, 4, DOpcodes, QOpcodes0, QOpcodes1); 03227 } 03228 03229 case Intrinsic::arm_neon_vst2lane: { 03230 static const uint16_t DOpcodes[] = { ARM::VST2LNd8Pseudo, 03231 ARM::VST2LNd16Pseudo, 03232 ARM::VST2LNd32Pseudo }; 03233 static const uint16_t QOpcodes[] = { ARM::VST2LNq16Pseudo, 03234 ARM::VST2LNq32Pseudo }; 03235 return SelectVLDSTLane(N, false, false, 2, DOpcodes, QOpcodes); 03236 } 03237 03238 case Intrinsic::arm_neon_vst3lane: { 03239 static const uint16_t DOpcodes[] = { ARM::VST3LNd8Pseudo, 03240 ARM::VST3LNd16Pseudo, 03241 ARM::VST3LNd32Pseudo }; 03242 static const uint16_t QOpcodes[] = { ARM::VST3LNq16Pseudo, 03243 ARM::VST3LNq32Pseudo }; 03244 return SelectVLDSTLane(N, false, false, 3, DOpcodes, QOpcodes); 03245 } 03246 03247 case Intrinsic::arm_neon_vst4lane: { 03248 static const uint16_t DOpcodes[] = { ARM::VST4LNd8Pseudo, 03249 ARM::VST4LNd16Pseudo, 03250 ARM::VST4LNd32Pseudo }; 03251 static const uint16_t QOpcodes[] = { ARM::VST4LNq16Pseudo, 03252 ARM::VST4LNq32Pseudo }; 03253 return SelectVLDSTLane(N, false, false, 4, DOpcodes, QOpcodes); 03254 } 03255 } 03256 break; 03257 } 03258 03259 case ISD::INTRINSIC_WO_CHAIN: { 03260 unsigned IntNo = cast<ConstantSDNode>(N->getOperand(0))->getZExtValue(); 03261 switch (IntNo) { 03262 default: 03263 break; 03264 03265 case Intrinsic::arm_neon_vtbl2: 03266 return SelectVTBL(N, false, 2, ARM::VTBL2); 03267 case Intrinsic::arm_neon_vtbl3: 03268 return SelectVTBL(N, false, 3, ARM::VTBL3Pseudo); 03269 case Intrinsic::arm_neon_vtbl4: 03270 return SelectVTBL(N, false, 4, ARM::VTBL4Pseudo); 03271 03272 case Intrinsic::arm_neon_vtbx2: 03273 return SelectVTBL(N, true, 2, ARM::VTBX2); 03274 case Intrinsic::arm_neon_vtbx3: 03275 return SelectVTBL(N, true, 3, ARM::VTBX3Pseudo); 03276 case Intrinsic::arm_neon_vtbx4: 03277 return SelectVTBL(N, true, 4, ARM::VTBX4Pseudo); 03278 } 03279 break; 03280 } 03281 03282 case ARMISD::VTBL1: { 03283 SDLoc dl(N); 03284 EVT VT = N->getValueType(0); 03285 SmallVector<SDValue, 6> Ops; 03286 03287 Ops.push_back(N->getOperand(0)); 03288 Ops.push_back(N->getOperand(1)); 03289 Ops.push_back(getAL(CurDAG)); // Predicate 03290 Ops.push_back(CurDAG->getRegister(0, MVT::i32)); // Predicate Register 03291 return CurDAG->getMachineNode(ARM::VTBL1, dl, VT, Ops); 03292 } 03293 case ARMISD::VTBL2: { 03294 SDLoc dl(N); 03295 EVT VT = N->getValueType(0); 03296 03297 // Form a REG_SEQUENCE to force register allocation. 03298 SDValue V0 = N->getOperand(0); 03299 SDValue V1 = N->getOperand(1); 03300 SDValue RegSeq = SDValue(createDRegPairNode(MVT::v16i8, V0, V1), 0); 03301 03302 SmallVector<SDValue, 6> Ops; 03303 Ops.push_back(RegSeq); 03304 Ops.push_back(N->getOperand(2)); 03305 Ops.push_back(getAL(CurDAG)); // Predicate 03306 Ops.push_back(CurDAG->getRegister(0, MVT::i32)); // Predicate Register 03307 return CurDAG->getMachineNode(ARM::VTBL2, dl, VT, Ops); 03308 } 03309 03310 case ISD::CONCAT_VECTORS: 03311 return SelectConcatVector(N); 03312 } 03313 03314 return SelectCode(N); 03315 } 03316 03317 SDNode *ARMDAGToDAGISel::SelectInlineAsm(SDNode *N){ 03318 std::vector<SDValue> AsmNodeOperands; 03319 unsigned Flag, Kind; 03320 bool Changed = false; 03321 unsigned NumOps = N->getNumOperands(); 03322 03323 // Normally, i64 data is bounded to two arbitrary GRPs for "%r" constraint. 03324 // However, some instrstions (e.g. ldrexd/strexd in ARM mode) require 03325 // (even/even+1) GPRs and use %n and %Hn to refer to the individual regs 03326 // respectively. Since there is no constraint to explicitly specify a 03327 // reg pair, we use GPRPair reg class for "%r" for 64-bit data. For Thumb, 03328 // the 64-bit data may be referred by H, Q, R modifiers, so we still pack 03329 // them into a GPRPair. 03330 03331 SDLoc dl(N); 03332 SDValue Glue = N->getGluedNode() ? N->getOperand(NumOps-1) 03333 : SDValue(nullptr,0); 03334 03335 SmallVector<bool, 8> OpChanged; 03336 // Glue node will be appended late. 03337 for(unsigned i = 0, e = N->getGluedNode() ? NumOps - 1 : NumOps; i < e; ++i) { 03338 SDValue op = N->getOperand(i); 03339 AsmNodeOperands.push_back(op); 03340 03341 if (i < InlineAsm::Op_FirstOperand) 03342 continue; 03343 03344 if (ConstantSDNode *C = dyn_cast<ConstantSDNode>(N->getOperand(i))) { 03345 Flag = C->getZExtValue(); 03346 Kind = InlineAsm::getKind(Flag); 03347 } 03348 else 03349 continue; 03350 03351 // Immediate operands to inline asm in the SelectionDAG are modeled with 03352 // two operands. The first is a constant of value InlineAsm::Kind_Imm, and 03353 // the second is a constant with the value of the immediate. If we get here 03354 // and we have a Kind_Imm, skip the next operand, and continue. 03355 if (Kind == InlineAsm::Kind_Imm) { 03356 SDValue op = N->getOperand(++i); 03357 AsmNodeOperands.push_back(op); 03358 continue; 03359 } 03360 03361 unsigned NumRegs = InlineAsm::getNumOperandRegisters(Flag); 03362 if (NumRegs) 03363 OpChanged.push_back(false); 03364 03365 unsigned DefIdx = 0; 03366 bool IsTiedToChangedOp = false; 03367 // If it's a use that is tied with a previous def, it has no 03368 // reg class constraint. 03369 if (Changed && InlineAsm::isUseOperandTiedToDef(Flag, DefIdx)) 03370 IsTiedToChangedOp = OpChanged[DefIdx]; 03371 03372 if (Kind != InlineAsm::Kind_RegUse && Kind != InlineAsm::Kind_RegDef 03373 && Kind != InlineAsm::Kind_RegDefEarlyClobber) 03374 continue; 03375 03376 unsigned RC; 03377 bool HasRC = InlineAsm::hasRegClassConstraint(Flag, RC); 03378 if ((!IsTiedToChangedOp && (!HasRC || RC != ARM::GPRRegClassID)) 03379 || NumRegs != 2) 03380 continue; 03381 03382 assert((i+2 < NumOps) && "Invalid number of operands in inline asm"); 03383 SDValue V0 = N->getOperand(i+1); 03384 SDValue V1 = N->getOperand(i+2); 03385 unsigned Reg0 = cast<RegisterSDNode>(V0)->getReg(); 03386 unsigned Reg1 = cast<RegisterSDNode>(V1)->getReg(); 03387 SDValue PairedReg; 03388 MachineRegisterInfo &MRI = MF->getRegInfo(); 03389 03390 if (Kind == InlineAsm::Kind_RegDef || 03391 Kind == InlineAsm::Kind_RegDefEarlyClobber) { 03392 // Replace the two GPRs with 1 GPRPair and copy values from GPRPair to 03393 // the original GPRs. 03394 03395 unsigned GPVR = MRI.createVirtualRegister(&ARM::GPRPairRegClass); 03396 PairedReg = CurDAG->getRegister(GPVR, MVT::Untyped); 03397 SDValue Chain = SDValue(N,0); 03398 03399 SDNode *GU = N->getGluedUser(); 03400 SDValue RegCopy = CurDAG->getCopyFromReg(Chain, dl, GPVR, MVT::Untyped, 03401 Chain.getValue(1)); 03402 03403 // Extract values from a GPRPair reg and copy to the original GPR reg. 03404 SDValue Sub0 = CurDAG->getTargetExtractSubreg(ARM::gsub_0, dl, MVT::i32, 03405 RegCopy); 03406 SDValue Sub1 = CurDAG->getTargetExtractSubreg(ARM::gsub_1, dl, MVT::i32, 03407 RegCopy); 03408 SDValue T0 = CurDAG->getCopyToReg(Sub0, dl, Reg0, Sub0, 03409 RegCopy.getValue(1)); 03410 SDValue T1 = CurDAG->getCopyToReg(Sub1, dl, Reg1, Sub1, T0.getValue(1)); 03411 03412 // Update the original glue user. 03413 std::vector<SDValue> Ops(GU->op_begin(), GU->op_end()-1); 03414 Ops.push_back(T1.getValue(1)); 03415 CurDAG->UpdateNodeOperands(GU, Ops); 03416 GU = T1.getNode(); 03417 } 03418 else { 03419 // For Kind == InlineAsm::Kind_RegUse, we first copy two GPRs into a 03420 // GPRPair and then pass the GPRPair to the inline asm. 03421 SDValue Chain = AsmNodeOperands[InlineAsm::Op_InputChain]; 03422 03423 // As REG_SEQ doesn't take RegisterSDNode, we copy them first. 03424 SDValue T0 = CurDAG->getCopyFromReg(Chain, dl, Reg0, MVT::i32, 03425 Chain.getValue(1)); 03426 SDValue T1 = CurDAG->getCopyFromReg(Chain, dl, Reg1, MVT::i32, 03427 T0.getValue(1)); 03428 SDValue Pair = SDValue(createGPRPairNode(MVT::Untyped, T0, T1), 0); 03429 03430 // Copy REG_SEQ into a GPRPair-typed VR and replace the original two 03431 // i32 VRs of inline asm with it. 03432 unsigned GPVR = MRI.createVirtualRegister(&ARM::GPRPairRegClass); 03433 PairedReg = CurDAG->getRegister(GPVR, MVT::Untyped); 03434 Chain = CurDAG->getCopyToReg(T1, dl, GPVR, Pair, T1.getValue(1)); 03435 03436 AsmNodeOperands[InlineAsm::Op_InputChain] = Chain; 03437 Glue = Chain.getValue(1); 03438 } 03439 03440 Changed = true; 03441 03442 if(PairedReg.getNode()) { 03443 OpChanged[OpChanged.size() -1 ] = true; 03444 Flag = InlineAsm::getFlagWord(Kind, 1 /* RegNum*/); 03445 if (IsTiedToChangedOp) 03446 Flag = InlineAsm::getFlagWordForMatchingOp(Flag, DefIdx); 03447 else 03448 Flag = InlineAsm::getFlagWordForRegClass(Flag, ARM::GPRPairRegClassID); 03449 // Replace the current flag. 03450 AsmNodeOperands[AsmNodeOperands.size() -1] = CurDAG->getTargetConstant( 03451 Flag, MVT::i32); 03452 // Add the new register node and skip the original two GPRs. 03453 AsmNodeOperands.push_back(PairedReg); 03454 // Skip the next two GPRs. 03455 i += 2; 03456 } 03457 } 03458 03459 if (Glue.getNode()) 03460 AsmNodeOperands.push_back(Glue); 03461 if (!Changed) 03462 return nullptr; 03463 03464 SDValue New = CurDAG->getNode(ISD::INLINEASM, SDLoc(N), 03465 CurDAG->getVTList(MVT::Other, MVT::Glue), AsmNodeOperands); 03466 New->setNodeId(-1); 03467 return New.getNode(); 03468 } 03469 03470 03471 bool ARMDAGToDAGISel:: 03472 SelectInlineAsmMemoryOperand(const SDValue &Op, char ConstraintCode, 03473 std::vector<SDValue> &OutOps) { 03474 assert(ConstraintCode == 'm' && "unexpected asm memory constraint"); 03475 // Require the address to be in a register. That is safe for all ARM 03476 // variants and it is hard to do anything much smarter without knowing 03477 // how the operand is used. 03478 OutOps.push_back(Op); 03479 return false; 03480 } 03481 03482 /// createARMISelDag - This pass converts a legalized DAG into a 03483 /// ARM-specific DAG, ready for instruction scheduling. 03484 /// 03485 FunctionPass *llvm::createARMISelDag(ARMBaseTargetMachine &TM, 03486 CodeGenOpt::Level OptLevel) { 03487 return new ARMDAGToDAGISel(TM, OptLevel); 03488 }