1894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman//===- BlackfinISelDAGToDAG.cpp - A dag to dag inst selector for Blackfin -===//
2894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman//
3894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman//                     The LLVM Compiler Infrastructure
4894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman//
5894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman// This file is distributed under the University of Illinois Open Source
6894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman// License. See LICENSE.TXT for details.
7894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman//
8894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman//===----------------------------------------------------------------------===//
9894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman//
10894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman// This file defines an instruction selector for the Blackfin target.
11894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman//
12894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman//===----------------------------------------------------------------------===//
13894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
14894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman#include "Blackfin.h"
15894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman#include "BlackfinTargetMachine.h"
16894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman#include "BlackfinRegisterInfo.h"
17894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman#include "llvm/Intrinsics.h"
18894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman#include "llvm/CodeGen/SelectionDAGISel.h"
19894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman#include "llvm/CodeGen/MachineRegisterInfo.h"
20894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman#include "llvm/Support/Compiler.h"
21894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman#include "llvm/Support/Debug.h"
22894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman#include "llvm/Support/ErrorHandling.h"
23894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman#include "llvm/Support/raw_ostream.h"
24894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
25894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Baumanusing namespace llvm;
26894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
27894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman//===----------------------------------------------------------------------===//
28894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman// Instruction Selector Implementation
29894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman//===----------------------------------------------------------------------===//
30894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
31894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman//===----------------------------------------------------------------------===//
32894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman/// BlackfinDAGToDAGISel - Blackfin specific code to select blackfin machine
33894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman/// instructions for SelectionDAG operations.
34894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Baumannamespace {
35894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  class BlackfinDAGToDAGISel : public SelectionDAGISel {
36894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    /// Subtarget - Keep a pointer to the Blackfin Subtarget around so that we
37894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    /// can make the right decision when generating code for different targets.
38894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    //const BlackfinSubtarget &Subtarget;
39894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  public:
40894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    BlackfinDAGToDAGISel(BlackfinTargetMachine &TM, CodeGenOpt::Level OptLevel)
41894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman      : SelectionDAGISel(TM, OptLevel) {}
42894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
43894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    virtual void PostprocessISelDAG();
44894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
45894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    virtual const char *getPassName() const {
46894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman      return "Blackfin DAG->DAG Pattern Instruction Selection";
47894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    }
48894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
49894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    // Include the pieces autogenerated from the target description.
50894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman#include "BlackfinGenDAGISel.inc"
51894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
52894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  private:
53894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    SDNode *Select(SDNode *N);
5419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman    bool SelectADDRspii(SDValue Addr, SDValue &Base, SDValue &Offset);
55894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
56894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    // Walk the DAG after instruction selection, fixing register class issues.
57894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    void FixRegisterClasses(SelectionDAG &DAG);
58894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
59894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    const BlackfinInstrInfo &getInstrInfo() {
60894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman      return *static_cast<const BlackfinTargetMachine&>(TM).getInstrInfo();
61894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    }
62894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    const BlackfinRegisterInfo *getRegisterInfo() {
63894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman      return static_cast<const BlackfinTargetMachine&>(TM).getRegisterInfo();
64894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    }
65894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  };
66894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman}  // end anonymous namespace
67894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
68894018228b0e0bdbd7aa7e8f47d4a9458789ca82John BaumanFunctionPass *llvm::createBlackfinISelDag(BlackfinTargetMachine &TM,
69894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman                                          CodeGenOpt::Level OptLevel) {
70894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  return new BlackfinDAGToDAGISel(TM, OptLevel);
71894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman}
72894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
73894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Baumanvoid BlackfinDAGToDAGISel::PostprocessISelDAG() {
74894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  FixRegisterClasses(*CurDAG);
75894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman}
76894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
77894018228b0e0bdbd7aa7e8f47d4a9458789ca82John BaumanSDNode *BlackfinDAGToDAGISel::Select(SDNode *N) {
78894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  if (N->isMachineOpcode())
79894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    return NULL;   // Already selected.
80894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
81894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  switch (N->getOpcode()) {
82894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  default: break;
83894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  case ISD::FrameIndex: {
84894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    // Selects to ADDpp FI, 0 which in turn will become ADDimm7 SP, imm or ADDpp
85894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    // SP, Px
86894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    int FI = cast<FrameIndexSDNode>(N)->getIndex();
87894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    SDValue TFI = CurDAG->getTargetFrameIndex(FI, MVT::i32);
88894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    return CurDAG->SelectNodeTo(N, BF::ADDpp, MVT::i32, TFI,
89894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman                                CurDAG->getTargetConstant(0, MVT::i32));
90894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  }
91894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  }
92894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
93894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  return SelectCode(N);
94894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman}
95894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
9619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Baumanbool BlackfinDAGToDAGISel::SelectADDRspii(SDValue Addr,
97894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman                                          SDValue &Base,
98894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman                                          SDValue &Offset) {
99894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  FrameIndexSDNode *FIN = 0;
100894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  if ((FIN = dyn_cast<FrameIndexSDNode>(Addr))) {
101894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), MVT::i32);
102894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    Offset = CurDAG->getTargetConstant(0, MVT::i32);
103894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    return true;
104894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  }
105894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  if (Addr.getOpcode() == ISD::ADD) {
106894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    ConstantSDNode *CN = 0;
107894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    if ((FIN = dyn_cast<FrameIndexSDNode>(Addr.getOperand(0))) &&
108894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman        (CN = dyn_cast<ConstantSDNode>(Addr.getOperand(1))) &&
109894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman        (CN->getSExtValue() % 4 == 0 && CN->getSExtValue() >= 0)) {
110894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman      // Constant positive word offset from frame index
111894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman      Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), MVT::i32);
112894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman      Offset = CurDAG->getTargetConstant(CN->getSExtValue(), MVT::i32);
113894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman      return true;
114894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    }
115894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  }
116894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  return false;
117894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman}
118894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
119894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Baumanstatic inline bool isCC(const TargetRegisterClass *RC) {
12019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  return BF::AnyCCRegClass.hasSubClassEq(RC);
121894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman}
122894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
123894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Baumanstatic inline bool isDCC(const TargetRegisterClass *RC) {
12419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  return BF::DRegClass.hasSubClassEq(RC) || isCC(RC);
125894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman}
126894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
127894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Baumanstatic void UpdateNodeOperand(SelectionDAG &DAG,
128894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman                              SDNode *N,
129894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman                              unsigned Num,
130894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman                              SDValue Val) {
131894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  SmallVector<SDValue, 8> ops(N->op_begin(), N->op_end());
132894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  ops[Num] = Val;
133894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  SDNode *New = DAG.UpdateNodeOperands(N, ops.data(), ops.size());
134894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  DAG.ReplaceAllUsesWith(N, New);
135894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman}
136894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
137894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman// After instruction selection, insert COPY_TO_REGCLASS nodes to help in
138894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman// choosing the proper register classes.
139894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Baumanvoid BlackfinDAGToDAGISel::FixRegisterClasses(SelectionDAG &DAG) {
140894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  const BlackfinInstrInfo &TII = getInstrInfo();
141894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  const BlackfinRegisterInfo *TRI = getRegisterInfo();
142894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  DAG.AssignTopologicalOrder();
143894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  HandleSDNode Dummy(DAG.getRoot());
144894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
145894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  for (SelectionDAG::allnodes_iterator NI = DAG.allnodes_begin();
146894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman       NI != DAG.allnodes_end(); ++NI) {
147894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    if (NI->use_empty() || !NI->isMachineOpcode())
148894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman      continue;
14919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman    const MCInstrDesc &DefMCID = TII.get(NI->getMachineOpcode());
150894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    for (SDNode::use_iterator UI = NI->use_begin(); !UI.atEnd(); ++UI) {
151894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman      if (!UI->isMachineOpcode())
152894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman        continue;
153894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
15419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman      if (UI.getUse().getResNo() >= DefMCID.getNumDefs())
155894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman        continue;
156894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman      const TargetRegisterClass *DefRC =
15719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman        TII.getRegClass(DefMCID, UI.getUse().getResNo(), TRI);
158894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
15919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman      const MCInstrDesc &UseMCID = TII.get(UI->getMachineOpcode());
16019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman      if (UseMCID.getNumDefs()+UI.getOperandNo() >= UseMCID.getNumOperands())
161894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman        continue;
162894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman      const TargetRegisterClass *UseRC =
16319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman        TII.getRegClass(UseMCID, UseMCID.getNumDefs()+UI.getOperandNo(), TRI);
164894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman      if (!DefRC || !UseRC)
165894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman        continue;
166894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman      // We cannot copy CC <-> !(CC/D)
167894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman      if ((isCC(DefRC) && !isDCC(UseRC)) || (isCC(UseRC) && !isDCC(DefRC))) {
168894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman        SDNode *Copy =
169894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman          DAG.getMachineNode(TargetOpcode::COPY_TO_REGCLASS,
170894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman                             NI->getDebugLoc(),
171894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman                             MVT::i32,
172894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman                             UI.getUse().get(),
173894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman                             DAG.getTargetConstant(BF::DRegClassID, MVT::i32));
174894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman        UpdateNodeOperand(DAG, *UI, UI.getOperandNo(), SDValue(Copy, 0));
175894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman      }
176894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    }
177894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  }
178894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  DAG.setRoot(Dummy.getValue());
179894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman}
180894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
181