template <> bool AVRDAGToDAGISel::select<ISD::STORE>(SDNode *N) { // Use the STD{W}SPQRr pseudo instruction when passing arguments through // the stack on function calls for further expansion during the PEI phase. const StoreSDNode *ST = cast<StoreSDNode>(N); SDValue BasePtr = ST->getBasePtr(); // Early exit when the base pointer is a frame index node or a constant. if (isa<FrameIndexSDNode>(BasePtr) || isa<ConstantSDNode>(BasePtr) || BasePtr.isUndef()) { return false; } const RegisterSDNode *RN = dyn_cast<RegisterSDNode>(BasePtr.getOperand(0)); // Only stores where SP is the base pointer are valid. if (!RN || (RN->getReg() != AVR::SP)) { return false; } int CST = (int)cast<ConstantSDNode>(BasePtr.getOperand(1))->getZExtValue(); SDValue Chain = ST->getChain(); EVT VT = ST->getValue().getValueType(); SDLoc DL(N); SDValue Offset = CurDAG->getTargetConstant(CST, DL, MVT::i16); SDValue Ops[] = {BasePtr.getOperand(0), Offset, ST->getValue(), Chain}; unsigned Opc = (VT == MVT::i16) ? AVR::STDWSPQRr : AVR::STDSPQRr; SDNode *ResNode = CurDAG->getMachineNode(Opc, DL, MVT::Other, Ops); // Transfer memory operands. MachineSDNode::mmo_iterator MemOp = MF->allocateMemRefsArray(1); MemOp[0] = ST->getMemOperand(); cast<MachineSDNode>(ResNode)->setMemRefs(MemOp, MemOp + 1); ReplaceUses(SDValue(N, 0), SDValue(ResNode, 0)); CurDAG->RemoveDeadNode(N); return true; }