SystemZISelDAGToDAG.cpp revision ac6d9bec671252dd1e596fa71180ff6b39d06b5d
1//===-- SystemZISelDAGToDAG.cpp - A dag to dag inst selector for SystemZ --===// 2// 3// The LLVM Compiler Infrastructure 4// 5// This file is distributed under the University of Illinois Open Source 6// License. See LICENSE.TXT for details. 7// 8//===----------------------------------------------------------------------===// 9// 10// This file defines an instruction selector for the SystemZ target. 11// 12//===----------------------------------------------------------------------===// 13 14#include "SystemZTargetMachine.h" 15#include "llvm/CodeGen/SelectionDAGISel.h" 16#include "llvm/Support/Debug.h" 17#include "llvm/Support/raw_ostream.h" 18 19using namespace llvm; 20 21namespace { 22// Used to build addressing modes. 23struct SystemZAddressingMode { 24 // The shape of the address. 25 enum AddrForm { 26 // base+displacement 27 FormBD, 28 29 // base+displacement+index for load and store operands 30 FormBDXNormal, 31 32 // base+displacement+index for load address operands 33 FormBDXLA, 34 35 // base+displacement+index+ADJDYNALLOC 36 FormBDXDynAlloc 37 }; 38 AddrForm Form; 39 40 // The type of displacement. The enum names here correspond directly 41 // to the definitions in SystemZOperand.td. We could split them into 42 // flags -- single/pair, 128-bit, etc. -- but it hardly seems worth it. 43 enum DispRange { 44 Disp12Only, 45 Disp12Pair, 46 Disp20Only, 47 Disp20Only128, 48 Disp20Pair 49 }; 50 DispRange DR; 51 52 // The parts of the address. The address is equivalent to: 53 // 54 // Base + Disp + Index + (IncludesDynAlloc ? ADJDYNALLOC : 0) 55 SDValue Base; 56 int64_t Disp; 57 SDValue Index; 58 bool IncludesDynAlloc; 59 60 SystemZAddressingMode(AddrForm form, DispRange dr) 61 : Form(form), DR(dr), Base(), Disp(0), Index(), 62 IncludesDynAlloc(false) {} 63 64 // True if the address can have an index register. 65 bool hasIndexField() { return Form != FormBD; } 66 67 // True if the address can (and must) include ADJDYNALLOC. 68 bool isDynAlloc() { return Form == FormBDXDynAlloc; } 69 70 void dump() { 71 errs() << "SystemZAddressingMode " << this << '\n'; 72 73 errs() << " Base "; 74 if (Base.getNode() != 0) 75 Base.getNode()->dump(); 76 else 77 errs() << "null\n"; 78 79 if (hasIndexField()) { 80 errs() << " Index "; 81 if (Index.getNode() != 0) 82 Index.getNode()->dump(); 83 else 84 errs() << "null\n"; 85 } 86 87 errs() << " Disp " << Disp; 88 if (IncludesDynAlloc) 89 errs() << " + ADJDYNALLOC"; 90 errs() << '\n'; 91 } 92}; 93 94class SystemZDAGToDAGISel : public SelectionDAGISel { 95 const SystemZTargetLowering &Lowering; 96 const SystemZSubtarget &Subtarget; 97 98 // Used by SystemZOperands.td to create integer constants. 99 inline SDValue getImm(const SDNode *Node, uint64_t Imm) { 100 return CurDAG->getTargetConstant(Imm, Node->getValueType(0)); 101 } 102 103 // Try to fold more of the base or index of AM into AM, where IsBase 104 // selects between the base and index. 105 bool expandAddress(SystemZAddressingMode &AM, bool IsBase); 106 107 // Try to describe N in AM, returning true on success. 108 bool selectAddress(SDValue N, SystemZAddressingMode &AM); 109 110 // Extract individual target operands from matched address AM. 111 void getAddressOperands(const SystemZAddressingMode &AM, EVT VT, 112 SDValue &Base, SDValue &Disp); 113 void getAddressOperands(const SystemZAddressingMode &AM, EVT VT, 114 SDValue &Base, SDValue &Disp, SDValue &Index); 115 116 // Try to match Addr as a FormBD address with displacement type DR. 117 // Return true on success, storing the base and displacement in 118 // Base and Disp respectively. 119 bool selectBDAddr(SystemZAddressingMode::DispRange DR, SDValue Addr, 120 SDValue &Base, SDValue &Disp); 121 122 // Try to match Addr as a FormBDX* address of form Form with 123 // displacement type DR. Return true on success, storing the base, 124 // displacement and index in Base, Disp and Index respectively. 125 bool selectBDXAddr(SystemZAddressingMode::AddrForm Form, 126 SystemZAddressingMode::DispRange DR, SDValue Addr, 127 SDValue &Base, SDValue &Disp, SDValue &Index); 128 129 // PC-relative address matching routines used by SystemZOperands.td. 130 bool selectPCRelAddress(SDValue Addr, SDValue &Target) { 131 if (Addr.getOpcode() == SystemZISD::PCREL_WRAPPER) { 132 Target = Addr.getOperand(0); 133 return true; 134 } 135 return false; 136 } 137 138 // BD matching routines used by SystemZOperands.td. 139 bool selectBDAddr12Only(SDValue Addr, SDValue &Base, SDValue &Disp) { 140 return selectBDAddr(SystemZAddressingMode::Disp12Only, Addr, Base, Disp); 141 } 142 bool selectBDAddr12Pair(SDValue Addr, SDValue &Base, SDValue &Disp) { 143 return selectBDAddr(SystemZAddressingMode::Disp12Pair, Addr, Base, Disp); 144 } 145 bool selectBDAddr20Only(SDValue Addr, SDValue &Base, SDValue &Disp) { 146 return selectBDAddr(SystemZAddressingMode::Disp20Only, Addr, Base, Disp); 147 } 148 bool selectBDAddr20Pair(SDValue Addr, SDValue &Base, SDValue &Disp) { 149 return selectBDAddr(SystemZAddressingMode::Disp20Pair, Addr, Base, Disp); 150 } 151 152 // BDX matching routines used by SystemZOperands.td. 153 bool selectBDXAddr12Only(SDValue Addr, SDValue &Base, SDValue &Disp, 154 SDValue &Index) { 155 return selectBDXAddr(SystemZAddressingMode::FormBDXNormal, 156 SystemZAddressingMode::Disp12Only, 157 Addr, Base, Disp, Index); 158 } 159 bool selectBDXAddr12Pair(SDValue Addr, SDValue &Base, SDValue &Disp, 160 SDValue &Index) { 161 return selectBDXAddr(SystemZAddressingMode::FormBDXNormal, 162 SystemZAddressingMode::Disp12Pair, 163 Addr, Base, Disp, Index); 164 } 165 bool selectDynAlloc12Only(SDValue Addr, SDValue &Base, SDValue &Disp, 166 SDValue &Index) { 167 return selectBDXAddr(SystemZAddressingMode::FormBDXDynAlloc, 168 SystemZAddressingMode::Disp12Only, 169 Addr, Base, Disp, Index); 170 } 171 bool selectBDXAddr20Only(SDValue Addr, SDValue &Base, SDValue &Disp, 172 SDValue &Index) { 173 return selectBDXAddr(SystemZAddressingMode::FormBDXNormal, 174 SystemZAddressingMode::Disp20Only, 175 Addr, Base, Disp, Index); 176 } 177 bool selectBDXAddr20Only128(SDValue Addr, SDValue &Base, SDValue &Disp, 178 SDValue &Index) { 179 return selectBDXAddr(SystemZAddressingMode::FormBDXNormal, 180 SystemZAddressingMode::Disp20Only128, 181 Addr, Base, Disp, Index); 182 } 183 bool selectBDXAddr20Pair(SDValue Addr, SDValue &Base, SDValue &Disp, 184 SDValue &Index) { 185 return selectBDXAddr(SystemZAddressingMode::FormBDXNormal, 186 SystemZAddressingMode::Disp20Pair, 187 Addr, Base, Disp, Index); 188 } 189 bool selectLAAddr12Pair(SDValue Addr, SDValue &Base, SDValue &Disp, 190 SDValue &Index) { 191 return selectBDXAddr(SystemZAddressingMode::FormBDXLA, 192 SystemZAddressingMode::Disp12Pair, 193 Addr, Base, Disp, Index); 194 } 195 bool selectLAAddr20Pair(SDValue Addr, SDValue &Base, SDValue &Disp, 196 SDValue &Index) { 197 return selectBDXAddr(SystemZAddressingMode::FormBDXLA, 198 SystemZAddressingMode::Disp20Pair, 199 Addr, Base, Disp, Index); 200 } 201 202 // If Op0 is null, then Node is a constant that can be loaded using: 203 // 204 // (Opcode UpperVal LowerVal) 205 // 206 // If Op0 is nonnull, then Node can be implemented using: 207 // 208 // (Opcode (Opcode Op0 UpperVal) LowerVal) 209 SDNode *splitLargeImmediate(unsigned Opcode, SDNode *Node, SDValue Op0, 210 uint64_t UpperVal, uint64_t LowerVal); 211 212public: 213 SystemZDAGToDAGISel(SystemZTargetMachine &TM, CodeGenOpt::Level OptLevel) 214 : SelectionDAGISel(TM, OptLevel), 215 Lowering(*TM.getTargetLowering()), 216 Subtarget(*TM.getSubtargetImpl()) { } 217 218 // Override MachineFunctionPass. 219 virtual const char *getPassName() const LLVM_OVERRIDE { 220 return "SystemZ DAG->DAG Pattern Instruction Selection"; 221 } 222 223 // Override SelectionDAGISel. 224 virtual SDNode *Select(SDNode *Node) LLVM_OVERRIDE; 225 virtual bool SelectInlineAsmMemoryOperand(const SDValue &Op, 226 char ConstraintCode, 227 std::vector<SDValue> &OutOps) 228 LLVM_OVERRIDE; 229 230 // Include the pieces autogenerated from the target description. 231 #include "SystemZGenDAGISel.inc" 232}; 233} // end anonymous namespace 234 235FunctionPass *llvm::createSystemZISelDag(SystemZTargetMachine &TM, 236 CodeGenOpt::Level OptLevel) { 237 return new SystemZDAGToDAGISel(TM, OptLevel); 238} 239 240// Return true if Val should be selected as a displacement for an address 241// with range DR. Here we're interested in the range of both the instruction 242// described by DR and of any pairing instruction. 243static bool selectDisp(SystemZAddressingMode::DispRange DR, int64_t Val) { 244 switch (DR) { 245 case SystemZAddressingMode::Disp12Only: 246 return isUInt<12>(Val); 247 248 case SystemZAddressingMode::Disp12Pair: 249 case SystemZAddressingMode::Disp20Only: 250 case SystemZAddressingMode::Disp20Pair: 251 return isInt<20>(Val); 252 253 case SystemZAddressingMode::Disp20Only128: 254 return isInt<20>(Val) && isInt<20>(Val + 8); 255 } 256 llvm_unreachable("Unhandled displacement range"); 257} 258 259// Change the base or index in AM to Value, where IsBase selects 260// between the base and index. 261static void changeComponent(SystemZAddressingMode &AM, bool IsBase, 262 SDValue Value) { 263 if (IsBase) 264 AM.Base = Value; 265 else 266 AM.Index = Value; 267} 268 269// The base or index of AM is equivalent to Value + ADJDYNALLOC, 270// where IsBase selects between the base and index. Try to fold the 271// ADJDYNALLOC into AM. 272static bool expandAdjDynAlloc(SystemZAddressingMode &AM, bool IsBase, 273 SDValue Value) { 274 if (AM.isDynAlloc() && !AM.IncludesDynAlloc) { 275 changeComponent(AM, IsBase, Value); 276 AM.IncludesDynAlloc = true; 277 return true; 278 } 279 return false; 280} 281 282// The base of AM is equivalent to Base + Index. Try to use Index as 283// the index register. 284static bool expandIndex(SystemZAddressingMode &AM, SDValue Base, 285 SDValue Index) { 286 if (AM.hasIndexField() && !AM.Index.getNode()) { 287 AM.Base = Base; 288 AM.Index = Index; 289 return true; 290 } 291 return false; 292} 293 294// The base or index of AM is equivalent to Op0 + Op1, where IsBase selects 295// between the base and index. Try to fold Op1 into AM's displacement. 296static bool expandDisp(SystemZAddressingMode &AM, bool IsBase, 297 SDValue Op0, ConstantSDNode *Op1) { 298 // First try adjusting the displacement. 299 int64_t TestDisp = AM.Disp + Op1->getSExtValue(); 300 if (selectDisp(AM.DR, TestDisp)) { 301 changeComponent(AM, IsBase, Op0); 302 AM.Disp = TestDisp; 303 return true; 304 } 305 306 // We could consider forcing the displacement into a register and 307 // using it as an index, but it would need to be carefully tuned. 308 return false; 309} 310 311bool SystemZDAGToDAGISel::expandAddress(SystemZAddressingMode &AM, 312 bool IsBase) { 313 SDValue N = IsBase ? AM.Base : AM.Index; 314 unsigned Opcode = N.getOpcode(); 315 if (Opcode == ISD::TRUNCATE) { 316 N = N.getOperand(0); 317 Opcode = N.getOpcode(); 318 } 319 if (Opcode == ISD::ADD || CurDAG->isBaseWithConstantOffset(N)) { 320 SDValue Op0 = N.getOperand(0); 321 SDValue Op1 = N.getOperand(1); 322 323 unsigned Op0Code = Op0->getOpcode(); 324 unsigned Op1Code = Op1->getOpcode(); 325 326 if (Op0Code == SystemZISD::ADJDYNALLOC) 327 return expandAdjDynAlloc(AM, IsBase, Op1); 328 if (Op1Code == SystemZISD::ADJDYNALLOC) 329 return expandAdjDynAlloc(AM, IsBase, Op0); 330 331 if (Op0Code == ISD::Constant) 332 return expandDisp(AM, IsBase, Op1, cast<ConstantSDNode>(Op0)); 333 if (Op1Code == ISD::Constant) 334 return expandDisp(AM, IsBase, Op0, cast<ConstantSDNode>(Op1)); 335 336 if (IsBase && expandIndex(AM, Op0, Op1)) 337 return true; 338 } 339 return false; 340} 341 342// Return true if an instruction with displacement range DR should be 343// used for displacement value Val. selectDisp(DR, Val) must already hold. 344static bool isValidDisp(SystemZAddressingMode::DispRange DR, int64_t Val) { 345 assert(selectDisp(DR, Val) && "Invalid displacement"); 346 switch (DR) { 347 case SystemZAddressingMode::Disp12Only: 348 case SystemZAddressingMode::Disp20Only: 349 case SystemZAddressingMode::Disp20Only128: 350 return true; 351 352 case SystemZAddressingMode::Disp12Pair: 353 // Use the other instruction if the displacement is too large. 354 return isUInt<12>(Val); 355 356 case SystemZAddressingMode::Disp20Pair: 357 // Use the other instruction if the displacement is small enough. 358 return !isUInt<12>(Val); 359 } 360 llvm_unreachable("Unhandled displacement range"); 361} 362 363// Return true if Base + Disp + Index should be performed by LA(Y). 364static bool shouldUseLA(SDNode *Base, int64_t Disp, SDNode *Index) { 365 // Don't use LA(Y) for constants. 366 if (!Base) 367 return false; 368 369 // Always use LA(Y) for frame addresses, since we know that the destination 370 // register is almost always (perhaps always) going to be different from 371 // the frame register. 372 if (Base->getOpcode() == ISD::FrameIndex) 373 return true; 374 375 if (Disp) { 376 // Always use LA(Y) if there is a base, displacement and index. 377 if (Index) 378 return true; 379 380 // Always use LA if the displacement is small enough. It should always 381 // be no worse than AGHI (and better if it avoids a move). 382 if (isUInt<12>(Disp)) 383 return true; 384 385 // For similar reasons, always use LAY if the constant is too big for AGHI. 386 // LAY should be no worse than AGFI. 387 if (!isInt<16>(Disp)) 388 return true; 389 } else { 390 // Don't use LA for plain registers. 391 if (!Index) 392 return false; 393 394 // Don't use LA for plain addition if the index operand is only used 395 // once. It should be a natural two-operand addition in that case. 396 if (Index->hasOneUse()) 397 return false; 398 399 // Prefer addition if the second operation is sign-extended, in the 400 // hope of using AGF. 401 unsigned IndexOpcode = Index->getOpcode(); 402 if (IndexOpcode == ISD::SIGN_EXTEND || 403 IndexOpcode == ISD::SIGN_EXTEND_INREG) 404 return false; 405 } 406 407 // Don't use LA for two-operand addition if either operand is only 408 // used once. The addition instructions are better in that case. 409 if (Base->hasOneUse()) 410 return false; 411 412 return true; 413} 414 415// Return true if Addr is suitable for AM, updating AM if so. 416bool SystemZDAGToDAGISel::selectAddress(SDValue Addr, 417 SystemZAddressingMode &AM) { 418 // Start out assuming that the address will need to be loaded separately, 419 // then try to extend it as much as we can. 420 AM.Base = Addr; 421 422 // First try treating the address as a constant. 423 if (Addr.getOpcode() == ISD::Constant && 424 expandDisp(AM, true, SDValue(), cast<ConstantSDNode>(Addr))) 425 ; 426 else 427 // Otherwise try expanding each component. 428 while (expandAddress(AM, true) || 429 (AM.Index.getNode() && expandAddress(AM, false))) 430 continue; 431 432 // Reject cases where it isn't profitable to use LA(Y). 433 if (AM.Form == SystemZAddressingMode::FormBDXLA && 434 !shouldUseLA(AM.Base.getNode(), AM.Disp, AM.Index.getNode())) 435 return false; 436 437 // Reject cases where the other instruction in a pair should be used. 438 if (!isValidDisp(AM.DR, AM.Disp)) 439 return false; 440 441 // Make sure that ADJDYNALLOC is included where necessary. 442 if (AM.isDynAlloc() && !AM.IncludesDynAlloc) 443 return false; 444 445 DEBUG(AM.dump()); 446 return true; 447} 448 449// Insert a node into the DAG at least before Pos. This will reposition 450// the node as needed, and will assign it a node ID that is <= Pos's ID. 451// Note that this does *not* preserve the uniqueness of node IDs! 452// The selection DAG must no longer depend on their uniqueness when this 453// function is used. 454static void insertDAGNode(SelectionDAG *DAG, SDNode *Pos, SDValue N) { 455 if (N.getNode()->getNodeId() == -1 || 456 N.getNode()->getNodeId() > Pos->getNodeId()) { 457 DAG->RepositionNode(Pos, N.getNode()); 458 N.getNode()->setNodeId(Pos->getNodeId()); 459 } 460} 461 462void SystemZDAGToDAGISel::getAddressOperands(const SystemZAddressingMode &AM, 463 EVT VT, SDValue &Base, 464 SDValue &Disp) { 465 Base = AM.Base; 466 if (!Base.getNode()) 467 // Register 0 means "no base". This is mostly useful for shifts. 468 Base = CurDAG->getRegister(0, VT); 469 else if (Base.getOpcode() == ISD::FrameIndex) { 470 // Lower a FrameIndex to a TargetFrameIndex. 471 int64_t FrameIndex = cast<FrameIndexSDNode>(Base)->getIndex(); 472 Base = CurDAG->getTargetFrameIndex(FrameIndex, VT); 473 } else if (Base.getValueType() != VT) { 474 // Truncate values from i64 to i32, for shifts. 475 assert(VT == MVT::i32 && Base.getValueType() == MVT::i64 && 476 "Unexpected truncation"); 477 SDLoc DL(Base); 478 SDValue Trunc = CurDAG->getNode(ISD::TRUNCATE, DL, VT, Base); 479 insertDAGNode(CurDAG, Base.getNode(), Trunc); 480 Base = Trunc; 481 } 482 483 // Lower the displacement to a TargetConstant. 484 Disp = CurDAG->getTargetConstant(AM.Disp, VT); 485} 486 487void SystemZDAGToDAGISel::getAddressOperands(const SystemZAddressingMode &AM, 488 EVT VT, SDValue &Base, 489 SDValue &Disp, SDValue &Index) { 490 getAddressOperands(AM, VT, Base, Disp); 491 492 Index = AM.Index; 493 if (!Index.getNode()) 494 // Register 0 means "no index". 495 Index = CurDAG->getRegister(0, VT); 496} 497 498bool SystemZDAGToDAGISel::selectBDAddr(SystemZAddressingMode::DispRange DR, 499 SDValue Addr, SDValue &Base, 500 SDValue &Disp) { 501 SystemZAddressingMode AM(SystemZAddressingMode::FormBD, DR); 502 if (!selectAddress(Addr, AM)) 503 return false; 504 505 getAddressOperands(AM, Addr.getValueType(), Base, Disp); 506 return true; 507} 508 509bool SystemZDAGToDAGISel::selectBDXAddr(SystemZAddressingMode::AddrForm Form, 510 SystemZAddressingMode::DispRange DR, 511 SDValue Addr, SDValue &Base, 512 SDValue &Disp, SDValue &Index) { 513 SystemZAddressingMode AM(Form, DR); 514 if (!selectAddress(Addr, AM)) 515 return false; 516 517 getAddressOperands(AM, Addr.getValueType(), Base, Disp, Index); 518 return true; 519} 520 521SDNode *SystemZDAGToDAGISel::splitLargeImmediate(unsigned Opcode, SDNode *Node, 522 SDValue Op0, uint64_t UpperVal, 523 uint64_t LowerVal) { 524 EVT VT = Node->getValueType(0); 525 SDLoc DL(Node); 526 SDValue Upper = CurDAG->getConstant(UpperVal, VT); 527 if (Op0.getNode()) 528 Upper = CurDAG->getNode(Opcode, DL, VT, Op0, Upper); 529 Upper = SDValue(Select(Upper.getNode()), 0); 530 531 SDValue Lower = CurDAG->getConstant(LowerVal, VT); 532 SDValue Or = CurDAG->getNode(Opcode, DL, VT, Upper, Lower); 533 return Or.getNode(); 534} 535 536SDNode *SystemZDAGToDAGISel::Select(SDNode *Node) { 537 // Dump information about the Node being selected 538 DEBUG(errs() << "Selecting: "; Node->dump(CurDAG); errs() << "\n"); 539 540 // If we have a custom node, we already have selected! 541 if (Node->isMachineOpcode()) { 542 DEBUG(errs() << "== "; Node->dump(CurDAG); errs() << "\n"); 543 return 0; 544 } 545 546 unsigned Opcode = Node->getOpcode(); 547 switch (Opcode) { 548 case ISD::OR: 549 case ISD::XOR: 550 // If this is a 64-bit operation in which both 32-bit halves are nonzero, 551 // split the operation into two. 552 if (Node->getValueType(0) == MVT::i64) 553 if (ConstantSDNode *Op1 = dyn_cast<ConstantSDNode>(Node->getOperand(1))) { 554 uint64_t Val = Op1->getZExtValue(); 555 if (!SystemZ::isImmLF(Val) && !SystemZ::isImmHF(Val)) 556 Node = splitLargeImmediate(Opcode, Node, Node->getOperand(0), 557 Val - uint32_t(Val), uint32_t(Val)); 558 } 559 break; 560 561 case ISD::Constant: 562 // If this is a 64-bit constant that is out of the range of LLILF, 563 // LLIHF and LGFI, split it into two 32-bit pieces. 564 if (Node->getValueType(0) == MVT::i64) { 565 uint64_t Val = cast<ConstantSDNode>(Node)->getZExtValue(); 566 if (!SystemZ::isImmLF(Val) && !SystemZ::isImmHF(Val) && !isInt<32>(Val)) 567 Node = splitLargeImmediate(ISD::OR, Node, SDValue(), 568 Val - uint32_t(Val), uint32_t(Val)); 569 } 570 break; 571 572 case ISD::ATOMIC_LOAD_SUB: 573 // Try to convert subtractions of constants to additions. 574 if (ConstantSDNode *Op2 = dyn_cast<ConstantSDNode>(Node->getOperand(2))) { 575 uint64_t Value = -Op2->getZExtValue(); 576 EVT VT = Node->getValueType(0); 577 if (VT == MVT::i32 || isInt<32>(Value)) { 578 SDValue Ops[] = { Node->getOperand(0), Node->getOperand(1), 579 CurDAG->getConstant(int32_t(Value), VT) }; 580 Node = CurDAG->MorphNodeTo(Node, ISD::ATOMIC_LOAD_ADD, 581 Node->getVTList(), Ops, array_lengthof(Ops)); 582 } 583 } 584 break; 585 } 586 587 // Select the default instruction 588 SDNode *ResNode = SelectCode(Node); 589 590 DEBUG(errs() << "=> "; 591 if (ResNode == NULL || ResNode == Node) 592 Node->dump(CurDAG); 593 else 594 ResNode->dump(CurDAG); 595 errs() << "\n"; 596 ); 597 return ResNode; 598} 599 600bool SystemZDAGToDAGISel:: 601SelectInlineAsmMemoryOperand(const SDValue &Op, 602 char ConstraintCode, 603 std::vector<SDValue> &OutOps) { 604 assert(ConstraintCode == 'm' && "Unexpected constraint code"); 605 // Accept addresses with short displacements, which are compatible 606 // with Q, R, S and T. But keep the index operand for future expansion. 607 SDValue Base, Disp, Index; 608 if (!selectBDXAddr(SystemZAddressingMode::FormBD, 609 SystemZAddressingMode::Disp12Only, 610 Op, Base, Disp, Index)) 611 return true; 612 OutOps.push_back(Base); 613 OutOps.push_back(Disp); 614 OutOps.push_back(Index); 615 return false; 616} 617