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