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 "ARMAddressingModes.h" 00016 #include "ARMConstantPoolValue.h" 00017 #include "ARMISelLowering.h" 00018 #include "ARMTargetMachine.h" 00019 #include "llvm/CallingConv.h" 00020 #include "llvm/Constants.h" 00021 #include "llvm/DerivedTypes.h" 00022 #include "llvm/Function.h" 00023 #include "llvm/Intrinsics.h" 00024 #include "llvm/CodeGen/MachineFrameInfo.h" 00025 #include "llvm/CodeGen/MachineFunction.h" 00026 #include "llvm/CodeGen/MachineInstrBuilder.h" 00027 #include "llvm/CodeGen/SelectionDAG.h" 00028 #include "llvm/CodeGen/SelectionDAGISel.h" 00029 #include "llvm/Target/TargetLowering.h" 00030 #include "llvm/Target/TargetOptions.h" 00031 #include "llvm/Support/Compiler.h" 00032 #include "llvm/Support/Debug.h" 00033 using namespace llvm; 00034 00035 //===--------------------------------------------------------------------===// 00036 /// ARMDAGToDAGISel - ARM specific code to select ARM machine 00037 /// instructions for SelectionDAG operations. 00038 /// 00039 namespace { 00040 class ARMDAGToDAGISel : public SelectionDAGISel { 00041 ARMTargetMachine &TM; 00042 00043 /// Subtarget - Keep a pointer to the ARMSubtarget around so that we can 00044 /// make the right decision when generating code for different targets. 00045 const ARMSubtarget *Subtarget; 00046 00047 public: 00048 explicit ARMDAGToDAGISel(ARMTargetMachine &tm) 00049 : SelectionDAGISel(tm), TM(tm), 00050 Subtarget(&TM.getSubtarget<ARMSubtarget>()) { 00051 } 00052 00053 virtual const char *getPassName() const { 00054 return "ARM Instruction Selection"; 00055 } 00056 00057 SDNode *Select(SDValue Op); 00058 virtual void InstructionSelect(); 00059 bool SelectAddrMode2(SDValue Op, SDValue N, SDValue &Base, 00060 SDValue &Offset, SDValue &Opc); 00061 bool SelectAddrMode2Offset(SDValue Op, SDValue N, 00062 SDValue &Offset, SDValue &Opc); 00063 bool SelectAddrMode3(SDValue Op, SDValue N, SDValue &Base, 00064 SDValue &Offset, SDValue &Opc); 00065 bool SelectAddrMode3Offset(SDValue Op, SDValue N, 00066 SDValue &Offset, SDValue &Opc); 00067 bool SelectAddrMode5(SDValue Op, SDValue N, SDValue &Base, 00068 SDValue &Offset); 00069 00070 bool SelectAddrModePC(SDValue Op, SDValue N, SDValue &Offset, 00071 SDValue &Label); 00072 00073 bool SelectThumbAddrModeRR(SDValue Op, SDValue N, SDValue &Base, 00074 SDValue &Offset); 00075 bool SelectThumbAddrModeRI5(SDValue Op, SDValue N, unsigned Scale, 00076 SDValue &Base, SDValue &OffImm, 00077 SDValue &Offset); 00078 bool SelectThumbAddrModeS1(SDValue Op, SDValue N, SDValue &Base, 00079 SDValue &OffImm, SDValue &Offset); 00080 bool SelectThumbAddrModeS2(SDValue Op, SDValue N, SDValue &Base, 00081 SDValue &OffImm, SDValue &Offset); 00082 bool SelectThumbAddrModeS4(SDValue Op, SDValue N, SDValue &Base, 00083 SDValue &OffImm, SDValue &Offset); 00084 bool SelectThumbAddrModeSP(SDValue Op, SDValue N, SDValue &Base, 00085 SDValue &OffImm); 00086 00087 bool SelectShifterOperandReg(SDValue Op, SDValue N, SDValue &A, 00088 SDValue &B, SDValue &C); 00089 00090 // Include the pieces autogenerated from the target description. 00091 #include "ARMGenDAGISel.inc" 00092 }; 00093 } 00094 00095 void ARMDAGToDAGISel::InstructionSelect() { 00096 DEBUG(BB->dump()); 00097 00098 SelectRoot(*CurDAG); 00099 CurDAG->RemoveDeadNodes(); 00100 } 00101 00102 bool ARMDAGToDAGISel::SelectAddrMode2(SDValue Op, SDValue N, 00103 SDValue &Base, SDValue &Offset, 00104 SDValue &Opc) { 00105 if (N.getOpcode() == ISD::MUL) { 00106 if (ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N.getOperand(1))) { 00107 // X * [3,5,9] -> X + X * [2,4,8] etc. 00108 int RHSC = (int)RHS->getZExtValue(); 00109 if (RHSC & 1) { 00110 RHSC = RHSC & ~1; 00111 ARM_AM::AddrOpc AddSub = ARM_AM::add; 00112 if (RHSC < 0) { 00113 AddSub = ARM_AM::sub; 00114 RHSC = - RHSC; 00115 } 00116 if (isPowerOf2_32(RHSC)) { 00117 unsigned ShAmt = Log2_32(RHSC); 00118 Base = Offset = N.getOperand(0); 00119 Opc = CurDAG->getTargetConstant(ARM_AM::getAM2Opc(AddSub, ShAmt, 00120 ARM_AM::lsl), 00121 MVT::i32); 00122 return true; 00123 } 00124 } 00125 } 00126 } 00127 00128 if (N.getOpcode() != ISD::ADD && N.getOpcode() != ISD::SUB) { 00129 Base = N; 00130 if (N.getOpcode() == ISD::FrameIndex) { 00131 int FI = cast<FrameIndexSDNode>(N)->getIndex(); 00132 Base = CurDAG->getTargetFrameIndex(FI, TLI.getPointerTy()); 00133 } else if (N.getOpcode() == ARMISD::Wrapper) { 00134 Base = N.getOperand(0); 00135 } 00136 Offset = CurDAG->getRegister(0, MVT::i32); 00137 Opc = CurDAG->getTargetConstant(ARM_AM::getAM2Opc(ARM_AM::add, 0, 00138 ARM_AM::no_shift), 00139 MVT::i32); 00140 return true; 00141 } 00142 00143 // Match simple R +/- imm12 operands. 00144 if (N.getOpcode() == ISD::ADD) 00145 if (ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N.getOperand(1))) { 00146 int RHSC = (int)RHS->getZExtValue(); 00147 if ((RHSC >= 0 && RHSC < 0x1000) || 00148 (RHSC < 0 && RHSC > -0x1000)) { // 12 bits. 00149 Base = N.getOperand(0); 00150 if (Base.getOpcode() == ISD::FrameIndex) { 00151 int FI = cast<FrameIndexSDNode>(Base)->getIndex(); 00152 Base = CurDAG->getTargetFrameIndex(FI, TLI.getPointerTy()); 00153 } 00154 Offset = CurDAG->getRegister(0, MVT::i32); 00155 00156 ARM_AM::AddrOpc AddSub = ARM_AM::add; 00157 if (RHSC < 0) { 00158 AddSub = ARM_AM::sub; 00159 RHSC = - RHSC; 00160 } 00161 Opc = CurDAG->getTargetConstant(ARM_AM::getAM2Opc(AddSub, RHSC, 00162 ARM_AM::no_shift), 00163 MVT::i32); 00164 return true; 00165 } 00166 } 00167 00168 // Otherwise this is R +/- [possibly shifted] R 00169 ARM_AM::AddrOpc AddSub = N.getOpcode() == ISD::ADD ? ARM_AM::add:ARM_AM::sub; 00170 ARM_AM::ShiftOpc ShOpcVal = ARM_AM::getShiftOpcForNode(N.getOperand(1)); 00171 unsigned ShAmt = 0; 00172 00173 Base = N.getOperand(0); 00174 Offset = N.getOperand(1); 00175 00176 if (ShOpcVal != ARM_AM::no_shift) { 00177 // Check to see if the RHS of the shift is a constant, if not, we can't fold 00178 // it. 00179 if (ConstantSDNode *Sh = 00180 dyn_cast<ConstantSDNode>(N.getOperand(1).getOperand(1))) { 00181 ShAmt = Sh->getZExtValue(); 00182 Offset = N.getOperand(1).getOperand(0); 00183 } else { 00184 ShOpcVal = ARM_AM::no_shift; 00185 } 00186 } 00187 00188 // Try matching (R shl C) + (R). 00189 if (N.getOpcode() == ISD::ADD && ShOpcVal == ARM_AM::no_shift) { 00190 ShOpcVal = ARM_AM::getShiftOpcForNode(N.getOperand(0)); 00191 if (ShOpcVal != ARM_AM::no_shift) { 00192 // Check to see if the RHS of the shift is a constant, if not, we can't 00193 // fold it. 00194 if (ConstantSDNode *Sh = 00195 dyn_cast<ConstantSDNode>(N.getOperand(0).getOperand(1))) { 00196 ShAmt = Sh->getZExtValue(); 00197 Offset = N.getOperand(0).getOperand(0); 00198 Base = N.getOperand(1); 00199 } else { 00200 ShOpcVal = ARM_AM::no_shift; 00201 } 00202 } 00203 } 00204 00205 Opc = CurDAG->getTargetConstant(ARM_AM::getAM2Opc(AddSub, ShAmt, ShOpcVal), 00206 MVT::i32); 00207 return true; 00208 } 00209 00210 bool ARMDAGToDAGISel::SelectAddrMode2Offset(SDValue Op, SDValue N, 00211 SDValue &Offset, SDValue &Opc) { 00212 unsigned Opcode = Op.getOpcode(); 00213 ISD::MemIndexedMode AM = (Opcode == ISD::LOAD) 00214 ? cast<LoadSDNode>(Op)->getAddressingMode() 00215 : cast<StoreSDNode>(Op)->getAddressingMode(); 00216 ARM_AM::AddrOpc AddSub = (AM == ISD::PRE_INC || AM == ISD::POST_INC) 00217 ? ARM_AM::add : ARM_AM::sub; 00218 if (ConstantSDNode *C = dyn_cast<ConstantSDNode>(N)) { 00219 int Val = (int)C->getZExtValue(); 00220 if (Val >= 0 && Val < 0x1000) { // 12 bits. 00221 Offset = CurDAG->getRegister(0, MVT::i32); 00222 Opc = CurDAG->getTargetConstant(ARM_AM::getAM2Opc(AddSub, Val, 00223 ARM_AM::no_shift), 00224 MVT::i32); 00225 return true; 00226 } 00227 } 00228 00229 Offset = N; 00230 ARM_AM::ShiftOpc ShOpcVal = ARM_AM::getShiftOpcForNode(N); 00231 unsigned ShAmt = 0; 00232 if (ShOpcVal != ARM_AM::no_shift) { 00233 // Check to see if the RHS of the shift is a constant, if not, we can't fold 00234 // it. 00235 if (ConstantSDNode *Sh = dyn_cast<ConstantSDNode>(N.getOperand(1))) { 00236 ShAmt = Sh->getZExtValue(); 00237 Offset = N.getOperand(0); 00238 } else { 00239 ShOpcVal = ARM_AM::no_shift; 00240 } 00241 } 00242 00243 Opc = CurDAG->getTargetConstant(ARM_AM::getAM2Opc(AddSub, ShAmt, ShOpcVal), 00244 MVT::i32); 00245 return true; 00246 } 00247 00248 00249 bool ARMDAGToDAGISel::SelectAddrMode3(SDValue Op, SDValue N, 00250 SDValue &Base, SDValue &Offset, 00251 SDValue &Opc) { 00252 if (N.getOpcode() == ISD::SUB) { 00253 // X - C is canonicalize to X + -C, no need to handle it here. 00254 Base = N.getOperand(0); 00255 Offset = N.getOperand(1); 00256 Opc = CurDAG->getTargetConstant(ARM_AM::getAM3Opc(ARM_AM::sub, 0),MVT::i32); 00257 return true; 00258 } 00259 00260 if (N.getOpcode() != ISD::ADD) { 00261 Base = N; 00262 if (N.getOpcode() == ISD::FrameIndex) { 00263 int FI = cast<FrameIndexSDNode>(N)->getIndex(); 00264 Base = CurDAG->getTargetFrameIndex(FI, TLI.getPointerTy()); 00265 } 00266 Offset = CurDAG->getRegister(0, MVT::i32); 00267 Opc = CurDAG->getTargetConstant(ARM_AM::getAM3Opc(ARM_AM::add, 0),MVT::i32); 00268 return true; 00269 } 00270 00271 // If the RHS is +/- imm8, fold into addr mode. 00272 if (ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N.getOperand(1))) { 00273 int RHSC = (int)RHS->getZExtValue(); 00274 if ((RHSC >= 0 && RHSC < 256) || 00275 (RHSC < 0 && RHSC > -256)) { // note -256 itself isn't allowed. 00276 Base = N.getOperand(0); 00277 if (Base.getOpcode() == ISD::FrameIndex) { 00278 int FI = cast<FrameIndexSDNode>(Base)->getIndex(); 00279 Base = CurDAG->getTargetFrameIndex(FI, TLI.getPointerTy()); 00280 } 00281 Offset = CurDAG->getRegister(0, MVT::i32); 00282 00283 ARM_AM::AddrOpc AddSub = ARM_AM::add; 00284 if (RHSC < 0) { 00285 AddSub = ARM_AM::sub; 00286 RHSC = - RHSC; 00287 } 00288 Opc = CurDAG->getTargetConstant(ARM_AM::getAM3Opc(AddSub, RHSC),MVT::i32); 00289 return true; 00290 } 00291 } 00292 00293 Base = N.getOperand(0); 00294 Offset = N.getOperand(1); 00295 Opc = CurDAG->getTargetConstant(ARM_AM::getAM3Opc(ARM_AM::add, 0), MVT::i32); 00296 return true; 00297 } 00298 00299 bool ARMDAGToDAGISel::SelectAddrMode3Offset(SDValue Op, SDValue N, 00300 SDValue &Offset, SDValue &Opc) { 00301 unsigned Opcode = Op.getOpcode(); 00302 ISD::MemIndexedMode AM = (Opcode == ISD::LOAD) 00303 ? cast<LoadSDNode>(Op)->getAddressingMode() 00304 : cast<StoreSDNode>(Op)->getAddressingMode(); 00305 ARM_AM::AddrOpc AddSub = (AM == ISD::PRE_INC || AM == ISD::POST_INC) 00306 ? ARM_AM::add : ARM_AM::sub; 00307 if (ConstantSDNode *C = dyn_cast<ConstantSDNode>(N)) { 00308 int Val = (int)C->getZExtValue(); 00309 if (Val >= 0 && Val < 256) { 00310 Offset = CurDAG->getRegister(0, MVT::i32); 00311 Opc = CurDAG->getTargetConstant(ARM_AM::getAM3Opc(AddSub, Val), MVT::i32); 00312 return true; 00313 } 00314 } 00315 00316 Offset = N; 00317 Opc = CurDAG->getTargetConstant(ARM_AM::getAM3Opc(AddSub, 0), MVT::i32); 00318 return true; 00319 } 00320 00321 00322 bool ARMDAGToDAGISel::SelectAddrMode5(SDValue Op, SDValue N, 00323 SDValue &Base, SDValue &Offset) { 00324 if (N.getOpcode() != ISD::ADD) { 00325 Base = N; 00326 if (N.getOpcode() == ISD::FrameIndex) { 00327 int FI = cast<FrameIndexSDNode>(N)->getIndex(); 00328 Base = CurDAG->getTargetFrameIndex(FI, TLI.getPointerTy()); 00329 } else if (N.getOpcode() == ARMISD::Wrapper) { 00330 Base = N.getOperand(0); 00331 } 00332 Offset = CurDAG->getTargetConstant(ARM_AM::getAM5Opc(ARM_AM::add, 0), 00333 MVT::i32); 00334 return true; 00335 } 00336 00337 // If the RHS is +/- imm8, fold into addr mode. 00338 if (ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N.getOperand(1))) { 00339 int RHSC = (int)RHS->getZExtValue(); 00340 if ((RHSC & 3) == 0) { // The constant is implicitly multiplied by 4. 00341 RHSC >>= 2; 00342 if ((RHSC >= 0 && RHSC < 256) || 00343 (RHSC < 0 && RHSC > -256)) { // note -256 itself isn't allowed. 00344 Base = N.getOperand(0); 00345 if (Base.getOpcode() == ISD::FrameIndex) { 00346 int FI = cast<FrameIndexSDNode>(Base)->getIndex(); 00347 Base = CurDAG->getTargetFrameIndex(FI, TLI.getPointerTy()); 00348 } 00349 00350 ARM_AM::AddrOpc AddSub = ARM_AM::add; 00351 if (RHSC < 0) { 00352 AddSub = ARM_AM::sub; 00353 RHSC = - RHSC; 00354 } 00355 Offset = CurDAG->getTargetConstant(ARM_AM::getAM5Opc(AddSub, RHSC), 00356 MVT::i32); 00357 return true; 00358 } 00359 } 00360 } 00361 00362 Base = N; 00363 Offset = CurDAG->getTargetConstant(ARM_AM::getAM5Opc(ARM_AM::add, 0), 00364 MVT::i32); 00365 return true; 00366 } 00367 00368 bool ARMDAGToDAGISel::SelectAddrModePC(SDValue Op, SDValue N, 00369 SDValue &Offset, SDValue &Label) { 00370 if (N.getOpcode() == ARMISD::PIC_ADD && N.hasOneUse()) { 00371 Offset = N.getOperand(0); 00372 SDValue N1 = N.getOperand(1); 00373 Label = CurDAG->getTargetConstant(cast<ConstantSDNode>(N1)->getZExtValue(), 00374 MVT::i32); 00375 return true; 00376 } 00377 return false; 00378 } 00379 00380 bool ARMDAGToDAGISel::SelectThumbAddrModeRR(SDValue Op, SDValue N, 00381 SDValue &Base, SDValue &Offset){ 00382 if (N.getOpcode() != ISD::ADD) { 00383 Base = N; 00384 // We must materialize a zero in a reg! Returning a constant here 00385 // wouldn't work without additional code to position the node within 00386 // ISel's topological ordering in a place where ISel will process it 00387 // normally. Instead, just explicitly issue a tMOVri8 node! 00388 Offset = SDValue(CurDAG->getTargetNode(ARM::tMOVi8, MVT::i32, 00389 CurDAG->getTargetConstant(0, MVT::i32)), 0); 00390 return true; 00391 } 00392 00393 Base = N.getOperand(0); 00394 Offset = N.getOperand(1); 00395 return true; 00396 } 00397 00398 bool 00399 ARMDAGToDAGISel::SelectThumbAddrModeRI5(SDValue Op, SDValue N, 00400 unsigned Scale, SDValue &Base, 00401 SDValue &OffImm, SDValue &Offset) { 00402 if (Scale == 4) { 00403 SDValue TmpBase, TmpOffImm; 00404 if (SelectThumbAddrModeSP(Op, N, TmpBase, TmpOffImm)) 00405 return false; // We want to select tLDRspi / tSTRspi instead. 00406 if (N.getOpcode() == ARMISD::Wrapper && 00407 N.getOperand(0).getOpcode() == ISD::TargetConstantPool) 00408 return false; // We want to select tLDRpci instead. 00409 } 00410 00411 if (N.getOpcode() != ISD::ADD) { 00412 Base = (N.getOpcode() == ARMISD::Wrapper) ? N.getOperand(0) : N; 00413 Offset = CurDAG->getRegister(0, MVT::i32); 00414 OffImm = CurDAG->getTargetConstant(0, MVT::i32); 00415 return true; 00416 } 00417 00418 // Thumb does not have [sp, r] address mode. 00419 RegisterSDNode *LHSR = dyn_cast<RegisterSDNode>(N.getOperand(0)); 00420 RegisterSDNode *RHSR = dyn_cast<RegisterSDNode>(N.getOperand(1)); 00421 if ((LHSR && LHSR->getReg() == ARM::SP) || 00422 (RHSR && RHSR->getReg() == ARM::SP)) { 00423 Base = N; 00424 Offset = CurDAG->getRegister(0, MVT::i32); 00425 OffImm = CurDAG->getTargetConstant(0, MVT::i32); 00426 return true; 00427 } 00428 00429 // If the RHS is + imm5 * scale, fold into addr mode. 00430 if (ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N.getOperand(1))) { 00431 int RHSC = (int)RHS->getZExtValue(); 00432 if ((RHSC & (Scale-1)) == 0) { // The constant is implicitly multiplied. 00433 RHSC /= Scale; 00434 if (RHSC >= 0 && RHSC < 32) { 00435 Base = N.getOperand(0); 00436 Offset = CurDAG->getRegister(0, MVT::i32); 00437 OffImm = CurDAG->getTargetConstant(RHSC, MVT::i32); 00438 return true; 00439 } 00440 } 00441 } 00442 00443 Base = N.getOperand(0); 00444 Offset = N.getOperand(1); 00445 OffImm = CurDAG->getTargetConstant(0, MVT::i32); 00446 return true; 00447 } 00448 00449 bool ARMDAGToDAGISel::SelectThumbAddrModeS1(SDValue Op, SDValue N, 00450 SDValue &Base, SDValue &OffImm, 00451 SDValue &Offset) { 00452 return SelectThumbAddrModeRI5(Op, N, 1, Base, OffImm, Offset); 00453 } 00454 00455 bool ARMDAGToDAGISel::SelectThumbAddrModeS2(SDValue Op, SDValue N, 00456 SDValue &Base, SDValue &OffImm, 00457 SDValue &Offset) { 00458 return SelectThumbAddrModeRI5(Op, N, 2, Base, OffImm, Offset); 00459 } 00460 00461 bool ARMDAGToDAGISel::SelectThumbAddrModeS4(SDValue Op, SDValue N, 00462 SDValue &Base, SDValue &OffImm, 00463 SDValue &Offset) { 00464 return SelectThumbAddrModeRI5(Op, N, 4, Base, OffImm, Offset); 00465 } 00466 00467 bool ARMDAGToDAGISel::SelectThumbAddrModeSP(SDValue Op, SDValue N, 00468 SDValue &Base, SDValue &OffImm) { 00469 if (N.getOpcode() == ISD::FrameIndex) { 00470 int FI = cast<FrameIndexSDNode>(N)->getIndex(); 00471 Base = CurDAG->getTargetFrameIndex(FI, TLI.getPointerTy()); 00472 OffImm = CurDAG->getTargetConstant(0, MVT::i32); 00473 return true; 00474 } 00475 00476 if (N.getOpcode() != ISD::ADD) 00477 return false; 00478 00479 RegisterSDNode *LHSR = dyn_cast<RegisterSDNode>(N.getOperand(0)); 00480 if (N.getOperand(0).getOpcode() == ISD::FrameIndex || 00481 (LHSR && LHSR->getReg() == ARM::SP)) { 00482 // If the RHS is + imm8 * scale, fold into addr mode. 00483 if (ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N.getOperand(1))) { 00484 int RHSC = (int)RHS->getZExtValue(); 00485 if ((RHSC & 3) == 0) { // The constant is implicitly multiplied. 00486 RHSC >>= 2; 00487 if (RHSC >= 0 && RHSC < 256) { 00488 Base = N.getOperand(0); 00489 if (Base.getOpcode() == ISD::FrameIndex) { 00490 int FI = cast<FrameIndexSDNode>(Base)->getIndex(); 00491 Base = CurDAG->getTargetFrameIndex(FI, TLI.getPointerTy()); 00492 } 00493 OffImm = CurDAG->getTargetConstant(RHSC, MVT::i32); 00494 return true; 00495 } 00496 } 00497 } 00498 } 00499 00500 return false; 00501 } 00502 00503 bool ARMDAGToDAGISel::SelectShifterOperandReg(SDValue Op, 00504 SDValue N, 00505 SDValue &BaseReg, 00506 SDValue &ShReg, 00507 SDValue &Opc) { 00508 ARM_AM::ShiftOpc ShOpcVal = ARM_AM::getShiftOpcForNode(N); 00509 00510 // Don't match base register only case. That is matched to a separate 00511 // lower complexity pattern with explicit register operand. 00512 if (ShOpcVal == ARM_AM::no_shift) return false; 00513 00514 BaseReg = N.getOperand(0); 00515 unsigned ShImmVal = 0; 00516 if (ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N.getOperand(1))) { 00517 ShReg = CurDAG->getRegister(0, MVT::i32); 00518 ShImmVal = RHS->getZExtValue() & 31; 00519 } else { 00520 ShReg = N.getOperand(1); 00521 } 00522 Opc = CurDAG->getTargetConstant(ARM_AM::getSORegOpc(ShOpcVal, ShImmVal), 00523 MVT::i32); 00524 return true; 00525 } 00526 00527 /// getAL - Returns a ARMCC::AL immediate node. 00528 static inline SDValue getAL(SelectionDAG *CurDAG) { 00529 return CurDAG->getTargetConstant((uint64_t)ARMCC::AL, MVT::i32); 00530 } 00531 00532 00533 SDNode *ARMDAGToDAGISel::Select(SDValue Op) { 00534 SDNode *N = Op.getNode(); 00535 00536 if (N->isMachineOpcode()) 00537 return NULL; // Already selected. 00538 00539 switch (N->getOpcode()) { 00540 default: break; 00541 case ISD::Constant: { 00542 unsigned Val = cast<ConstantSDNode>(N)->getZExtValue(); 00543 bool UseCP = true; 00544 if (Subtarget->isThumb()) 00545 UseCP = (Val > 255 && // MOV 00546 ~Val > 255 && // MOV + MVN 00547 !ARM_AM::isThumbImmShiftedVal(Val)); // MOV + LSL 00548 else 00549 UseCP = (ARM_AM::getSOImmVal(Val) == -1 && // MOV 00550 ARM_AM::getSOImmVal(~Val) == -1 && // MVN 00551 !ARM_AM::isSOImmTwoPartVal(Val)); // two instrs. 00552 if (UseCP) { 00553 SDValue CPIdx = 00554 CurDAG->getTargetConstantPool(ConstantInt::get(Type::Int32Ty, Val), 00555 TLI.getPointerTy()); 00556 00557 SDNode *ResNode; 00558 if (Subtarget->isThumb()) 00559 ResNode = CurDAG->getTargetNode(ARM::tLDRcp, MVT::i32, MVT::Other, 00560 CPIdx, CurDAG->getEntryNode()); 00561 else { 00562 SDValue Ops[] = { 00563 CPIdx, 00564 CurDAG->getRegister(0, MVT::i32), 00565 CurDAG->getTargetConstant(0, MVT::i32), 00566 getAL(CurDAG), 00567 CurDAG->getRegister(0, MVT::i32), 00568 CurDAG->getEntryNode() 00569 }; 00570 ResNode=CurDAG->getTargetNode(ARM::LDRcp, MVT::i32, MVT::Other, Ops, 6); 00571 } 00572 ReplaceUses(Op, SDValue(ResNode, 0)); 00573 return NULL; 00574 } 00575 00576 // Other cases are autogenerated. 00577 break; 00578 } 00579 case ISD::FrameIndex: { 00580 // Selects to ADDri FI, 0 which in turn will become ADDri SP, imm. 00581 int FI = cast<FrameIndexSDNode>(N)->getIndex(); 00582 SDValue TFI = CurDAG->getTargetFrameIndex(FI, TLI.getPointerTy()); 00583 if (Subtarget->isThumb()) 00584 return CurDAG->SelectNodeTo(N, ARM::tADDrSPi, MVT::i32, TFI, 00585 CurDAG->getTargetConstant(0, MVT::i32)); 00586 else { 00587 SDValue Ops[] = { TFI, CurDAG->getTargetConstant(0, MVT::i32), 00588 getAL(CurDAG), CurDAG->getRegister(0, MVT::i32), 00589 CurDAG->getRegister(0, MVT::i32) }; 00590 return CurDAG->SelectNodeTo(N, ARM::ADDri, MVT::i32, Ops, 5); 00591 } 00592 } 00593 case ISD::ADD: { 00594 // Select add sp, c to tADDhirr. 00595 SDValue N0 = Op.getOperand(0); 00596 SDValue N1 = Op.getOperand(1); 00597 RegisterSDNode *LHSR = dyn_cast<RegisterSDNode>(Op.getOperand(0)); 00598 RegisterSDNode *RHSR = dyn_cast<RegisterSDNode>(Op.getOperand(1)); 00599 if (LHSR && LHSR->getReg() == ARM::SP) { 00600 std::swap(N0, N1); 00601 std::swap(LHSR, RHSR); 00602 } 00603 if (RHSR && RHSR->getReg() == ARM::SP) { 00604 return CurDAG->SelectNodeTo(N, ARM::tADDhirr, Op.getValueType(), N0, N1); 00605 } 00606 break; 00607 } 00608 case ISD::MUL: 00609 if (Subtarget->isThumb()) 00610 break; 00611 if (ConstantSDNode *C = dyn_cast<ConstantSDNode>(Op.getOperand(1))) { 00612 unsigned RHSV = C->getZExtValue(); 00613 if (!RHSV) break; 00614 if (isPowerOf2_32(RHSV-1)) { // 2^n+1? 00615 SDValue V = Op.getOperand(0); 00616 unsigned ShImm = ARM_AM::getSORegOpc(ARM_AM::lsl, Log2_32(RHSV-1)); 00617 SDValue Ops[] = { V, V, CurDAG->getRegister(0, MVT::i32), 00618 CurDAG->getTargetConstant(ShImm, MVT::i32), 00619 getAL(CurDAG), CurDAG->getRegister(0, MVT::i32), 00620 CurDAG->getRegister(0, MVT::i32) }; 00621 return CurDAG->SelectNodeTo(N, ARM::ADDrs, MVT::i32, Ops, 7); 00622 } 00623 if (isPowerOf2_32(RHSV+1)) { // 2^n-1? 00624 SDValue V = Op.getOperand(0); 00625 unsigned ShImm = ARM_AM::getSORegOpc(ARM_AM::lsl, Log2_32(RHSV+1)); 00626 SDValue Ops[] = { V, V, CurDAG->getRegister(0, MVT::i32), 00627 CurDAG->getTargetConstant(ShImm, MVT::i32), 00628 getAL(CurDAG), CurDAG->getRegister(0, MVT::i32), 00629 CurDAG->getRegister(0, MVT::i32) }; 00630 return CurDAG->SelectNodeTo(N, ARM::RSBrs, MVT::i32, Ops, 7); 00631 } 00632 } 00633 break; 00634 case ARMISD::FMRRD: 00635 return CurDAG->getTargetNode(ARM::FMRRD, MVT::i32, MVT::i32, 00636 Op.getOperand(0), getAL(CurDAG), 00637 CurDAG->getRegister(0, MVT::i32)); 00638 case ISD::UMUL_LOHI: { 00639 SDValue Ops[] = { Op.getOperand(0), Op.getOperand(1), 00640 getAL(CurDAG), CurDAG->getRegister(0, MVT::i32), 00641 CurDAG->getRegister(0, MVT::i32) }; 00642 return CurDAG->getTargetNode(ARM::UMULL, MVT::i32, MVT::i32, Ops, 5); 00643 } 00644 case ISD::SMUL_LOHI: { 00645 SDValue Ops[] = { Op.getOperand(0), Op.getOperand(1), 00646 getAL(CurDAG), CurDAG->getRegister(0, MVT::i32), 00647 CurDAG->getRegister(0, MVT::i32) }; 00648 return CurDAG->getTargetNode(ARM::SMULL, MVT::i32, MVT::i32, Ops, 5); 00649 } 00650 case ISD::LOAD: { 00651 LoadSDNode *LD = cast<LoadSDNode>(Op); 00652 ISD::MemIndexedMode AM = LD->getAddressingMode(); 00653 MVT LoadedVT = LD->getMemoryVT(); 00654 if (AM != ISD::UNINDEXED) { 00655 SDValue Offset, AMOpc; 00656 bool isPre = (AM == ISD::PRE_INC) || (AM == ISD::PRE_DEC); 00657 unsigned Opcode = 0; 00658 bool Match = false; 00659 if (LoadedVT == MVT::i32 && 00660 SelectAddrMode2Offset(Op, LD->getOffset(), Offset, AMOpc)) { 00661 Opcode = isPre ? ARM::LDR_PRE : ARM::LDR_POST; 00662 Match = true; 00663 } else if (LoadedVT == MVT::i16 && 00664 SelectAddrMode3Offset(Op, LD->getOffset(), Offset, AMOpc)) { 00665 Match = true; 00666 Opcode = (LD->getExtensionType() == ISD::SEXTLOAD) 00667 ? (isPre ? ARM::LDRSH_PRE : ARM::LDRSH_POST) 00668 : (isPre ? ARM::LDRH_PRE : ARM::LDRH_POST); 00669 } else if (LoadedVT == MVT::i8 || LoadedVT == MVT::i1) { 00670 if (LD->getExtensionType() == ISD::SEXTLOAD) { 00671 if (SelectAddrMode3Offset(Op, LD->getOffset(), Offset, AMOpc)) { 00672 Match = true; 00673 Opcode = isPre ? ARM::LDRSB_PRE : ARM::LDRSB_POST; 00674 } 00675 } else { 00676 if (SelectAddrMode2Offset(Op, LD->getOffset(), Offset, AMOpc)) { 00677 Match = true; 00678 Opcode = isPre ? ARM::LDRB_PRE : ARM::LDRB_POST; 00679 } 00680 } 00681 } 00682 00683 if (Match) { 00684 SDValue Chain = LD->getChain(); 00685 SDValue Base = LD->getBasePtr(); 00686 SDValue Ops[]= { Base, Offset, AMOpc, getAL(CurDAG), 00687 CurDAG->getRegister(0, MVT::i32), Chain }; 00688 return CurDAG->getTargetNode(Opcode, MVT::i32, MVT::i32, 00689 MVT::Other, Ops, 6); 00690 } 00691 } 00692 // Other cases are autogenerated. 00693 break; 00694 } 00695 case ARMISD::BRCOND: { 00696 // Pattern: (ARMbrcond:void (bb:Other):$dst, (imm:i32):$cc) 00697 // Emits: (Bcc:void (bb:Other):$dst, (imm:i32):$cc) 00698 // Pattern complexity = 6 cost = 1 size = 0 00699 00700 // Pattern: (ARMbrcond:void (bb:Other):$dst, (imm:i32):$cc) 00701 // Emits: (tBcc:void (bb:Other):$dst, (imm:i32):$cc) 00702 // Pattern complexity = 6 cost = 1 size = 0 00703 00704 unsigned Opc = Subtarget->isThumb() ? ARM::tBcc : ARM::Bcc; 00705 SDValue Chain = Op.getOperand(0); 00706 SDValue N1 = Op.getOperand(1); 00707 SDValue N2 = Op.getOperand(2); 00708 SDValue N3 = Op.getOperand(3); 00709 SDValue InFlag = Op.getOperand(4); 00710 assert(N1.getOpcode() == ISD::BasicBlock); 00711 assert(N2.getOpcode() == ISD::Constant); 00712 assert(N3.getOpcode() == ISD::Register); 00713 00714 SDValue Tmp2 = CurDAG->getTargetConstant(((unsigned) 00715 cast<ConstantSDNode>(N2)->getZExtValue()), 00716 MVT::i32); 00717 SDValue Ops[] = { N1, Tmp2, N3, Chain, InFlag }; 00718 SDNode *ResNode = CurDAG->getTargetNode(Opc, MVT::Other, MVT::Flag, Ops, 5); 00719 Chain = SDValue(ResNode, 0); 00720 if (Op.getNode()->getNumValues() == 2) { 00721 InFlag = SDValue(ResNode, 1); 00722 ReplaceUses(SDValue(Op.getNode(), 1), InFlag); 00723 } 00724 ReplaceUses(SDValue(Op.getNode(), 0), SDValue(Chain.getNode(), Chain.getResNo())); 00725 return NULL; 00726 } 00727 case ARMISD::CMOV: { 00728 bool isThumb = Subtarget->isThumb(); 00729 MVT VT = Op.getValueType(); 00730 SDValue N0 = Op.getOperand(0); 00731 SDValue N1 = Op.getOperand(1); 00732 SDValue N2 = Op.getOperand(2); 00733 SDValue N3 = Op.getOperand(3); 00734 SDValue InFlag = Op.getOperand(4); 00735 assert(N2.getOpcode() == ISD::Constant); 00736 assert(N3.getOpcode() == ISD::Register); 00737 00738 // Pattern: (ARMcmov:i32 GPR:i32:$false, so_reg:i32:$true, (imm:i32):$cc) 00739 // Emits: (MOVCCs:i32 GPR:i32:$false, so_reg:i32:$true, (imm:i32):$cc) 00740 // Pattern complexity = 18 cost = 1 size = 0 00741 SDValue CPTmp0; 00742 SDValue CPTmp1; 00743 SDValue CPTmp2; 00744 if (!isThumb && VT == MVT::i32 && 00745 SelectShifterOperandReg(Op, N1, CPTmp0, CPTmp1, CPTmp2)) { 00746 SDValue Tmp2 = CurDAG->getTargetConstant(((unsigned) 00747 cast<ConstantSDNode>(N2)->getZExtValue()), 00748 MVT::i32); 00749 SDValue Ops[] = { N0, CPTmp0, CPTmp1, CPTmp2, Tmp2, N3, InFlag }; 00750 return CurDAG->SelectNodeTo(Op.getNode(), ARM::MOVCCs, MVT::i32, Ops, 7); 00751 } 00752 00753 // Pattern: (ARMcmov:i32 GPR:i32:$false, 00754 // (imm:i32)<<P:Predicate_so_imm>><<X:so_imm_XFORM>>:$true, 00755 // (imm:i32):$cc) 00756 // Emits: (MOVCCi:i32 GPR:i32:$false, 00757 // (so_imm_XFORM:i32 (imm:i32):$true), (imm:i32):$cc) 00758 // Pattern complexity = 10 cost = 1 size = 0 00759 if (VT == MVT::i32 && 00760 N3.getOpcode() == ISD::Constant && 00761 Predicate_so_imm(N3.getNode())) { 00762 SDValue Tmp1 = CurDAG->getTargetConstant(((unsigned) 00763 cast<ConstantSDNode>(N1)->getZExtValue()), 00764 MVT::i32); 00765 Tmp1 = Transform_so_imm_XFORM(Tmp1.getNode()); 00766 SDValue Tmp2 = CurDAG->getTargetConstant(((unsigned) 00767 cast<ConstantSDNode>(N2)->getZExtValue()), 00768 MVT::i32); 00769 SDValue Ops[] = { N0, Tmp1, Tmp2, N3, InFlag }; 00770 return CurDAG->SelectNodeTo(Op.getNode(), ARM::MOVCCi, MVT::i32, Ops, 5); 00771 } 00772 00773 // Pattern: (ARMcmov:i32 GPR:i32:$false, GPR:i32:$true, (imm:i32):$cc) 00774 // Emits: (MOVCCr:i32 GPR:i32:$false, GPR:i32:$true, (imm:i32):$cc) 00775 // Pattern complexity = 6 cost = 1 size = 0 00776 // 00777 // Pattern: (ARMcmov:i32 GPR:i32:$false, GPR:i32:$true, (imm:i32):$cc) 00778 // Emits: (tMOVCCr:i32 GPR:i32:$false, GPR:i32:$true, (imm:i32):$cc) 00779 // Pattern complexity = 6 cost = 11 size = 0 00780 // 00781 // Also FCPYScc and FCPYDcc. 00782 SDValue Tmp2 = CurDAG->getTargetConstant(((unsigned) 00783 cast<ConstantSDNode>(N2)->getZExtValue()), 00784 MVT::i32); 00785 SDValue Ops[] = { N0, N1, Tmp2, N3, InFlag }; 00786 unsigned Opc = 0; 00787 switch (VT.getSimpleVT()) { 00788 default: assert(false && "Illegal conditional move type!"); 00789 break; 00790 case MVT::i32: 00791 Opc = isThumb ? ARM::tMOVCCr : ARM::MOVCCr; 00792 break; 00793 case MVT::f32: 00794 Opc = ARM::FCPYScc; 00795 break; 00796 case MVT::f64: 00797 Opc = ARM::FCPYDcc; 00798 break; 00799 } 00800 return CurDAG->SelectNodeTo(Op.getNode(), Opc, VT, Ops, 5); 00801 } 00802 case ARMISD::CNEG: { 00803 MVT VT = Op.getValueType(); 00804 SDValue N0 = Op.getOperand(0); 00805 SDValue N1 = Op.getOperand(1); 00806 SDValue N2 = Op.getOperand(2); 00807 SDValue N3 = Op.getOperand(3); 00808 SDValue InFlag = Op.getOperand(4); 00809 assert(N2.getOpcode() == ISD::Constant); 00810 assert(N3.getOpcode() == ISD::Register); 00811 00812 SDValue Tmp2 = CurDAG->getTargetConstant(((unsigned) 00813 cast<ConstantSDNode>(N2)->getZExtValue()), 00814 MVT::i32); 00815 SDValue Ops[] = { N0, N1, Tmp2, N3, InFlag }; 00816 unsigned Opc = 0; 00817 switch (VT.getSimpleVT()) { 00818 default: assert(false && "Illegal conditional move type!"); 00819 break; 00820 case MVT::f32: 00821 Opc = ARM::FNEGScc; 00822 break; 00823 case MVT::f64: 00824 Opc = ARM::FNEGDcc; 00825 break; 00826 } 00827 return CurDAG->SelectNodeTo(Op.getNode(), Opc, VT, Ops, 5); 00828 } 00829 00830 case ISD::DECLARE: { 00831 SDValue Chain = Op.getOperand(0); 00832 SDValue N1 = Op.getOperand(1); 00833 SDValue N2 = Op.getOperand(2); 00834 FrameIndexSDNode *FINode = dyn_cast<FrameIndexSDNode>(N1); 00835 if (!FINode) 00836 break; 00837 if (N2.getOpcode() == ARMISD::PIC_ADD && isa<LoadSDNode>(N2.getOperand(0))) 00838 N2 = N2.getOperand(0); 00839 LoadSDNode *Ld = dyn_cast<LoadSDNode>(N2); 00840 if (!Ld) 00841 break; 00842 SDValue BasePtr = Ld->getBasePtr(); 00843 assert(BasePtr.getOpcode() == ARMISD::Wrapper && 00844 isa<ConstantPoolSDNode>(BasePtr.getOperand(0)) && 00845 "llvm.dbg.variable should be a constantpool node"); 00846 ConstantPoolSDNode *CP = cast<ConstantPoolSDNode>(BasePtr.getOperand(0)); 00847 GlobalValue *GV = 0; 00848 if (CP->isMachineConstantPoolEntry()) { 00849 ARMConstantPoolValue *ACPV = (ARMConstantPoolValue*)CP->getMachineCPVal(); 00850 GV = ACPV->getGV(); 00851 } else 00852 GV = dyn_cast<GlobalValue>(CP->getConstVal()); 00853 if (GV) { 00854 SDValue Tmp1 = CurDAG->getTargetFrameIndex(FINode->getIndex(), 00855 TLI.getPointerTy()); 00856 SDValue Tmp2 = CurDAG->getTargetGlobalAddress(GV, TLI.getPointerTy()); 00857 SDValue Ops[] = { Tmp1, Tmp2, Chain }; 00858 return CurDAG->getTargetNode(TargetInstrInfo::DECLARE, 00859 MVT::Other, Ops, 3); 00860 } 00861 break; 00862 } 00863 } 00864 00865 return SelectCode(Op); 00866 } 00867 00868 /// createARMISelDag - This pass converts a legalized DAG into a 00869 /// ARM-specific DAG, ready for instruction scheduling. 00870 /// 00871 FunctionPass *llvm::createARMISelDag(ARMTargetMachine &TM) { 00872 return new ARMDAGToDAGISel(TM); 00873 }