MSP430ISelDAGToDAG.cpp revision 198090
1193323Sed//===-- MSP430ISelDAGToDAG.cpp - A dag to dag inst selector for MSP430 ----===// 2193323Sed// 3193323Sed// The LLVM Compiler Infrastructure 4193323Sed// 5193323Sed// This file is distributed under the University of Illinois Open Source 6193323Sed// License. See LICENSE.TXT for details. 7193323Sed// 8193323Sed//===----------------------------------------------------------------------===// 9193323Sed// 10193323Sed// This file defines an instruction selector for the MSP430 target. 11193323Sed// 12193323Sed//===----------------------------------------------------------------------===// 13193323Sed 14193323Sed#include "MSP430.h" 15193323Sed#include "MSP430ISelLowering.h" 16193323Sed#include "MSP430TargetMachine.h" 17193323Sed#include "llvm/DerivedTypes.h" 18193323Sed#include "llvm/Function.h" 19193323Sed#include "llvm/Intrinsics.h" 20193323Sed#include "llvm/CallingConv.h" 21193323Sed#include "llvm/Constants.h" 22193323Sed#include "llvm/CodeGen/MachineFrameInfo.h" 23193323Sed#include "llvm/CodeGen/MachineFunction.h" 24193323Sed#include "llvm/CodeGen/MachineInstrBuilder.h" 25193323Sed#include "llvm/CodeGen/MachineRegisterInfo.h" 26193323Sed#include "llvm/CodeGen/SelectionDAG.h" 27193323Sed#include "llvm/CodeGen/SelectionDAGISel.h" 28193323Sed#include "llvm/Target/TargetLowering.h" 29193323Sed#include "llvm/Support/Compiler.h" 30193323Sed#include "llvm/Support/Debug.h" 31198090Srdivacky#include "llvm/Support/ErrorHandling.h" 32198090Srdivacky#include "llvm/Support/raw_ostream.h" 33198090Srdivacky#include "llvm/ADT/Statistic.h" 34198090Srdivacky 35193323Sedusing namespace llvm; 36193323Sed 37198090SrdivackySTATISTIC(NumLoadMoved, "Number of loads moved below TokenFactor"); 38198090Srdivacky 39193323Sed/// MSP430DAGToDAGISel - MSP430 specific code to select MSP430 machine 40193323Sed/// instructions for SelectionDAG operations. 41193323Sed/// 42193323Sednamespace { 43193323Sed class MSP430DAGToDAGISel : public SelectionDAGISel { 44193323Sed MSP430TargetLowering &Lowering; 45193323Sed const MSP430Subtarget &Subtarget; 46193323Sed 47193323Sed public: 48193323Sed MSP430DAGToDAGISel(MSP430TargetMachine &TM, CodeGenOpt::Level OptLevel) 49193323Sed : SelectionDAGISel(TM, OptLevel), 50193323Sed Lowering(*TM.getTargetLowering()), 51193323Sed Subtarget(*TM.getSubtargetImpl()) { } 52193323Sed 53193323Sed virtual void InstructionSelect(); 54193323Sed 55193323Sed virtual const char *getPassName() const { 56193323Sed return "MSP430 DAG->DAG Pattern Instruction Selection"; 57193323Sed } 58193323Sed 59198090Srdivacky virtual bool 60198090Srdivacky SelectInlineAsmMemoryOperand(const SDValue &Op, char ConstraintCode, 61198090Srdivacky std::vector<SDValue> &OutOps); 62198090Srdivacky 63193323Sed // Include the pieces autogenerated from the target description. 64193323Sed #include "MSP430GenDAGISel.inc" 65193323Sed 66193323Sed private: 67198090Srdivacky void PreprocessForRMW(); 68193323Sed SDNode *Select(SDValue Op); 69193323Sed bool SelectAddr(SDValue Op, SDValue Addr, SDValue &Base, SDValue &Disp); 70193323Sed 71193323Sed #ifndef NDEBUG 72193323Sed unsigned Indent; 73193323Sed #endif 74193323Sed }; 75193323Sed} // end anonymous namespace 76193323Sed 77193323Sed/// createMSP430ISelDag - This pass converts a legalized DAG into a 78193323Sed/// MSP430-specific DAG, ready for instruction scheduling. 79193323Sed/// 80193323SedFunctionPass *llvm::createMSP430ISelDag(MSP430TargetMachine &TM, 81193323Sed CodeGenOpt::Level OptLevel) { 82193323Sed return new MSP430DAGToDAGISel(TM, OptLevel); 83193323Sed} 84193323Sed 85193323Sed// FIXME: This is pretty dummy routine and needs to be rewritten in the future. 86193323Sedbool MSP430DAGToDAGISel::SelectAddr(SDValue Op, SDValue Addr, 87193323Sed SDValue &Base, SDValue &Disp) { 88193323Sed // Try to match frame address first. 89193323Sed if (FrameIndexSDNode *FIN = dyn_cast<FrameIndexSDNode>(Addr)) { 90193323Sed Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), MVT::i16); 91193323Sed Disp = CurDAG->getTargetConstant(0, MVT::i16); 92193323Sed return true; 93193323Sed } 94193323Sed 95193323Sed switch (Addr.getOpcode()) { 96193323Sed case ISD::ADD: 97193323Sed // Operand is a result from ADD with constant operand which fits into i16. 98193323Sed if (ConstantSDNode *CN = dyn_cast<ConstantSDNode>(Addr.getOperand(1))) { 99193323Sed uint64_t CVal = CN->getZExtValue(); 100193323Sed // Offset should fit into 16 bits. 101193323Sed if (((CVal << 48) >> 48) == CVal) { 102193323Sed SDValue N0 = Addr.getOperand(0); 103193323Sed if (FrameIndexSDNode *FIN = dyn_cast<FrameIndexSDNode>(N0)) 104193323Sed Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), MVT::i16); 105193323Sed else 106193323Sed Base = N0; 107193323Sed 108193323Sed Disp = CurDAG->getTargetConstant(CVal, MVT::i16); 109193323Sed return true; 110193323Sed } 111193323Sed } 112193323Sed break; 113193323Sed case MSP430ISD::Wrapper: 114193323Sed SDValue N0 = Addr.getOperand(0); 115193323Sed if (GlobalAddressSDNode *G = dyn_cast<GlobalAddressSDNode>(N0)) { 116193323Sed Base = CurDAG->getTargetGlobalAddress(G->getGlobal(), 117193323Sed MVT::i16, G->getOffset()); 118193323Sed Disp = CurDAG->getTargetConstant(0, MVT::i16); 119193323Sed return true; 120193323Sed } else if (ExternalSymbolSDNode *E = dyn_cast<ExternalSymbolSDNode>(N0)) { 121193323Sed Base = CurDAG->getTargetExternalSymbol(E->getSymbol(), MVT::i16); 122193323Sed Disp = CurDAG->getTargetConstant(0, MVT::i16); 123193323Sed } 124193323Sed break; 125193323Sed }; 126193323Sed 127193323Sed Base = Addr; 128193323Sed Disp = CurDAG->getTargetConstant(0, MVT::i16); 129193323Sed 130193323Sed return true; 131193323Sed} 132193323Sed 133193323Sed 134198090Srdivackybool MSP430DAGToDAGISel:: 135198090SrdivackySelectInlineAsmMemoryOperand(const SDValue &Op, char ConstraintCode, 136198090Srdivacky std::vector<SDValue> &OutOps) { 137198090Srdivacky SDValue Op0, Op1; 138198090Srdivacky switch (ConstraintCode) { 139198090Srdivacky default: return true; 140198090Srdivacky case 'm': // memory 141198090Srdivacky if (!SelectAddr(Op, Op, Op0, Op1)) 142198090Srdivacky return true; 143198090Srdivacky break; 144198090Srdivacky } 145193323Sed 146198090Srdivacky OutOps.push_back(Op0); 147198090Srdivacky OutOps.push_back(Op1); 148198090Srdivacky return false; 149198090Srdivacky} 150198090Srdivacky 151198090Srdivacky/// MoveBelowTokenFactor - Replace TokenFactor operand with load's chain operand 152198090Srdivacky/// and move load below the TokenFactor. Replace store's chain operand with 153198090Srdivacky/// load's chain result. 154198090Srdivacky/// Shamelessly stolen from X86. 155198090Srdivackystatic void MoveBelowTokenFactor(SelectionDAG *CurDAG, SDValue Load, 156198090Srdivacky SDValue Store, SDValue TF) { 157198090Srdivacky SmallVector<SDValue, 4> Ops; 158198090Srdivacky bool isRMW = false; 159198090Srdivacky SDValue TF0, TF1, NewTF; 160198090Srdivacky for (unsigned i = 0, e = TF.getNode()->getNumOperands(); i != e; ++i) 161198090Srdivacky if (Load.getNode() == TF.getOperand(i).getNode()) { 162198090Srdivacky TF0 = Load.getOperand(0); 163198090Srdivacky Ops.push_back(TF0); 164198090Srdivacky } else { 165198090Srdivacky TF1 = TF.getOperand(i); 166198090Srdivacky Ops.push_back(TF1); 167198090Srdivacky if (LoadSDNode* LD = dyn_cast<LoadSDNode>(TF1)) 168198090Srdivacky isRMW = !LD->isVolatile(); 169198090Srdivacky } 170198090Srdivacky 171198090Srdivacky if (isRMW && TF1.getOperand(0).getNode() == TF0.getNode()) 172198090Srdivacky NewTF = TF0; 173198090Srdivacky else 174198090Srdivacky NewTF = CurDAG->UpdateNodeOperands(TF, &Ops[0], Ops.size()); 175198090Srdivacky 176198090Srdivacky SDValue NewLoad = CurDAG->UpdateNodeOperands(Load, NewTF, 177198090Srdivacky Load.getOperand(1), 178198090Srdivacky Load.getOperand(2)); 179198090Srdivacky CurDAG->UpdateNodeOperands(Store, NewLoad.getValue(1), Store.getOperand(1), 180198090Srdivacky Store.getOperand(2), Store.getOperand(3)); 181198090Srdivacky} 182198090Srdivacky 183198090Srdivacky/// isRMWLoad - Return true if N is a load that's part of RMW sub-DAG. The chain 184198090Srdivacky/// produced by the load must only be used by the store's chain operand, 185198090Srdivacky/// otherwise this may produce a cycle in the DAG. 186198090Srdivacky/// Shamelessly stolen from X86. FIXME: Should we make this function common? 187198090Srdivackystatic bool isRMWLoad(SDValue N, SDValue Chain, SDValue Address, 188198090Srdivacky SDValue &Load) { 189198090Srdivacky if (N.getOpcode() == ISD::BIT_CONVERT) 190198090Srdivacky N = N.getOperand(0); 191198090Srdivacky 192198090Srdivacky LoadSDNode *LD = dyn_cast<LoadSDNode>(N); 193198090Srdivacky if (!LD || LD->isVolatile()) 194198090Srdivacky return false; 195198090Srdivacky if (LD->getAddressingMode() != ISD::UNINDEXED) 196198090Srdivacky return false; 197198090Srdivacky 198198090Srdivacky ISD::LoadExtType ExtType = LD->getExtensionType(); 199198090Srdivacky if (ExtType != ISD::NON_EXTLOAD && ExtType != ISD::EXTLOAD) 200198090Srdivacky return false; 201198090Srdivacky 202198090Srdivacky if (N.hasOneUse() && 203198090Srdivacky LD->hasNUsesOfValue(1, 1) && 204198090Srdivacky N.getOperand(1) == Address && 205198090Srdivacky LD->isOperandOf(Chain.getNode())) { 206198090Srdivacky Load = N; 207198090Srdivacky return true; 208198090Srdivacky } 209198090Srdivacky return false; 210198090Srdivacky} 211198090Srdivacky 212198090Srdivacky/// PreprocessForRMW - Preprocess the DAG to make instruction selection better. 213198090Srdivacky/// Shamelessly stolen from X86. 214198090Srdivackyvoid MSP430DAGToDAGISel::PreprocessForRMW() { 215198090Srdivacky for (SelectionDAG::allnodes_iterator I = CurDAG->allnodes_begin(), 216198090Srdivacky E = CurDAG->allnodes_end(); I != E; ++I) { 217198090Srdivacky if (!ISD::isNON_TRUNCStore(I)) 218198090Srdivacky continue; 219198090Srdivacky 220198090Srdivacky SDValue Chain = I->getOperand(0); 221198090Srdivacky if (Chain.getNode()->getOpcode() != ISD::TokenFactor) 222198090Srdivacky continue; 223198090Srdivacky 224198090Srdivacky SDValue N1 = I->getOperand(1); // Value to store 225198090Srdivacky SDValue N2 = I->getOperand(2); // Address of store 226198090Srdivacky 227198090Srdivacky if (!N1.hasOneUse()) 228198090Srdivacky continue; 229198090Srdivacky 230198090Srdivacky bool RModW = false; 231198090Srdivacky SDValue Load; 232198090Srdivacky unsigned Opcode = N1.getNode()->getOpcode(); 233198090Srdivacky switch (Opcode) { 234198090Srdivacky case ISD::ADD: 235198090Srdivacky case ISD::AND: 236198090Srdivacky case ISD::OR: 237198090Srdivacky case ISD::XOR: 238198090Srdivacky case ISD::ADDC: 239198090Srdivacky case ISD::ADDE: { 240198090Srdivacky SDValue N10 = N1.getOperand(0); 241198090Srdivacky SDValue N11 = N1.getOperand(1); 242198090Srdivacky RModW = isRMWLoad(N10, Chain, N2, Load); 243198090Srdivacky 244198090Srdivacky if (!RModW && isRMWLoad(N11, Chain, N2, Load)) { 245198090Srdivacky // Swap the operands, making the RMW load the first operand seems 246198090Srdivacky // to help selection and prevent token chain loops. 247198090Srdivacky N1 = CurDAG->UpdateNodeOperands(N1, N11, N10); 248198090Srdivacky RModW = true; 249198090Srdivacky } 250198090Srdivacky break; 251198090Srdivacky } 252198090Srdivacky case ISD::SUB: 253198090Srdivacky case ISD::SUBC: 254198090Srdivacky case ISD::SUBE: { 255198090Srdivacky SDValue N10 = N1.getOperand(0); 256198090Srdivacky RModW = isRMWLoad(N10, Chain, N2, Load); 257198090Srdivacky break; 258198090Srdivacky } 259198090Srdivacky } 260198090Srdivacky 261198090Srdivacky if (RModW) { 262198090Srdivacky MoveBelowTokenFactor(CurDAG, Load, SDValue(I, 0), Chain); 263198090Srdivacky ++NumLoadMoved; 264198090Srdivacky } 265198090Srdivacky } 266198090Srdivacky} 267198090Srdivacky 268193323Sed/// InstructionSelect - This callback is invoked by 269193323Sed/// SelectionDAGISel when it has created a SelectionDAG for us to codegen. 270193323Sedvoid MSP430DAGToDAGISel::InstructionSelect() { 271198090Srdivacky PreprocessForRMW(); 272198090Srdivacky 273198090Srdivacky DEBUG(errs() << "Selection DAG after RMW preprocessing:\n"); 274198090Srdivacky DEBUG(CurDAG->dump()); 275198090Srdivacky 276193323Sed DEBUG(BB->dump()); 277193323Sed 278193323Sed // Codegen the basic block. 279198090Srdivacky DEBUG(errs() << "===== Instruction selection begins:\n"); 280198090Srdivacky DEBUG(Indent = 0); 281193323Sed SelectRoot(*CurDAG); 282198090Srdivacky DEBUG(errs() << "===== Instruction selection ends:\n"); 283193323Sed 284193323Sed CurDAG->RemoveDeadNodes(); 285193323Sed} 286193323Sed 287193323SedSDNode *MSP430DAGToDAGISel::Select(SDValue Op) { 288193323Sed SDNode *Node = Op.getNode(); 289193323Sed DebugLoc dl = Op.getDebugLoc(); 290193323Sed 291193323Sed // Dump information about the Node being selected 292198090Srdivacky DEBUG(errs().indent(Indent) << "Selecting: "); 293193323Sed DEBUG(Node->dump(CurDAG)); 294198090Srdivacky DEBUG(errs() << "\n"); 295198090Srdivacky DEBUG(Indent += 2); 296193323Sed 297193323Sed // If we have a custom node, we already have selected! 298193323Sed if (Node->isMachineOpcode()) { 299198090Srdivacky DEBUG(errs().indent(Indent-2) << "== "; 300198090Srdivacky Node->dump(CurDAG); 301198090Srdivacky errs() << "\n"); 302198090Srdivacky DEBUG(Indent -= 2); 303193323Sed return NULL; 304193323Sed } 305193323Sed 306193323Sed // Few custom selection stuff. 307193323Sed switch (Node->getOpcode()) { 308193323Sed default: break; 309193323Sed case ISD::FrameIndex: { 310193323Sed assert(Op.getValueType() == MVT::i16); 311193323Sed int FI = cast<FrameIndexSDNode>(Node)->getIndex(); 312193323Sed SDValue TFI = CurDAG->getTargetFrameIndex(FI, MVT::i16); 313193323Sed if (Node->hasOneUse()) 314193323Sed return CurDAG->SelectNodeTo(Node, MSP430::ADD16ri, MVT::i16, 315193323Sed TFI, CurDAG->getTargetConstant(0, MVT::i16)); 316198090Srdivacky return CurDAG->getMachineNode(MSP430::ADD16ri, dl, MVT::i16, 317198090Srdivacky TFI, CurDAG->getTargetConstant(0, MVT::i16)); 318193323Sed } 319193323Sed } 320193323Sed 321193323Sed // Select the default instruction 322193323Sed SDNode *ResNode = SelectCode(Op); 323193323Sed 324198090Srdivacky DEBUG(errs() << std::string(Indent-2, ' ') << "=> "); 325193323Sed if (ResNode == NULL || ResNode == Op.getNode()) 326193323Sed DEBUG(Op.getNode()->dump(CurDAG)); 327193323Sed else 328193323Sed DEBUG(ResNode->dump(CurDAG)); 329198090Srdivacky DEBUG(errs() << "\n"); 330198090Srdivacky DEBUG(Indent -= 2); 331193323Sed 332193323Sed return ResNode; 333193323Sed} 334