move target-independent opcodes out of TargetInstrInfo
[oota-llvm.git] / lib / Target / Blackfin / BlackfinISelDAGToDAG.cpp
1 //===- BlackfinISelDAGToDAG.cpp - A dag to dag inst selector for Blackfin -===//
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 Blackfin target.
11 //
12 //===----------------------------------------------------------------------===//
13
14 #include "Blackfin.h"
15 #include "BlackfinISelLowering.h"
16 #include "BlackfinTargetMachine.h"
17 #include "BlackfinRegisterInfo.h"
18 #include "llvm/Intrinsics.h"
19 #include "llvm/CodeGen/SelectionDAGISel.h"
20 #include "llvm/CodeGen/MachineRegisterInfo.h"
21 #include "llvm/Support/Compiler.h"
22 #include "llvm/Support/Debug.h"
23 #include "llvm/Support/ErrorHandling.h"
24 #include "llvm/Support/raw_ostream.h"
25
26 using namespace llvm;
27
28 //===----------------------------------------------------------------------===//
29 // Instruction Selector Implementation
30 //===----------------------------------------------------------------------===//
31
32 //===----------------------------------------------------------------------===//
33 /// BlackfinDAGToDAGISel - Blackfin specific code to select blackfin machine
34 /// instructions for SelectionDAG operations.
35 namespace {
36   class BlackfinDAGToDAGISel : public SelectionDAGISel {
37     /// Subtarget - Keep a pointer to the Blackfin Subtarget around so that we
38     /// can make the right decision when generating code for different targets.
39     //const BlackfinSubtarget &Subtarget;
40   public:
41     BlackfinDAGToDAGISel(BlackfinTargetMachine &TM, CodeGenOpt::Level OptLevel)
42       : SelectionDAGISel(TM, OptLevel) {}
43
44     virtual void InstructionSelect();
45
46     virtual const char *getPassName() const {
47       return "Blackfin DAG->DAG Pattern Instruction Selection";
48     }
49
50     // Include the pieces autogenerated from the target description.
51 #include "BlackfinGenDAGISel.inc"
52
53   private:
54     SDNode *Select(SDNode *N);
55     bool SelectADDRspii(SDNode *Op, SDValue Addr,
56                         SDValue &Base, SDValue &Offset);
57
58     // Walk the DAG after instruction selection, fixing register class issues.
59     void FixRegisterClasses(SelectionDAG &DAG);
60
61     const BlackfinInstrInfo &getInstrInfo() {
62       return *static_cast<const BlackfinTargetMachine&>(TM).getInstrInfo();
63     }
64     const BlackfinRegisterInfo *getRegisterInfo() {
65       return static_cast<const BlackfinTargetMachine&>(TM).getRegisterInfo();
66     }
67   };
68 }  // end anonymous namespace
69
70 FunctionPass *llvm::createBlackfinISelDag(BlackfinTargetMachine &TM,
71                                           CodeGenOpt::Level OptLevel) {
72   return new BlackfinDAGToDAGISel(TM, OptLevel);
73 }
74
75 /// InstructionSelect - This callback is invoked by
76 /// SelectionDAGISel when it has created a SelectionDAG for us to codegen.
77 void BlackfinDAGToDAGISel::InstructionSelect() {
78   // Select target instructions for the DAG.
79   SelectRoot(*CurDAG);
80   DEBUG(errs() << "Selected selection DAG before regclass fixup:\n");
81   DEBUG(CurDAG->dump());
82   FixRegisterClasses(*CurDAG);
83 }
84
85 SDNode *BlackfinDAGToDAGISel::Select(SDNode *N) {
86   if (N->isMachineOpcode())
87     return NULL;   // Already selected.
88
89   switch (N->getOpcode()) {
90   default: break;
91   case ISD::FrameIndex: {
92     // Selects to ADDpp FI, 0 which in turn will become ADDimm7 SP, imm or ADDpp
93     // SP, Px
94     int FI = cast<FrameIndexSDNode>(N)->getIndex();
95     SDValue TFI = CurDAG->getTargetFrameIndex(FI, MVT::i32);
96     return CurDAG->SelectNodeTo(N, BF::ADDpp, MVT::i32, TFI,
97                                 CurDAG->getTargetConstant(0, MVT::i32));
98   }
99   }
100
101   return SelectCode(N);
102 }
103
104 bool BlackfinDAGToDAGISel::SelectADDRspii(SDNode *Op,
105                                           SDValue Addr,
106                                           SDValue &Base,
107                                           SDValue &Offset) {
108   FrameIndexSDNode *FIN = 0;
109   if ((FIN = dyn_cast<FrameIndexSDNode>(Addr))) {
110     Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), MVT::i32);
111     Offset = CurDAG->getTargetConstant(0, MVT::i32);
112     return true;
113   }
114   if (Addr.getOpcode() == ISD::ADD) {
115     ConstantSDNode *CN = 0;
116     if ((FIN = dyn_cast<FrameIndexSDNode>(Addr.getOperand(0))) &&
117         (CN = dyn_cast<ConstantSDNode>(Addr.getOperand(1))) &&
118         (CN->getSExtValue() % 4 == 0 && CN->getSExtValue() >= 0)) {
119       // Constant positive word offset from frame index
120       Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), MVT::i32);
121       Offset = CurDAG->getTargetConstant(CN->getSExtValue(), MVT::i32);
122       return true;
123     }
124   }
125   return false;
126 }
127
128 static inline bool isCC(const TargetRegisterClass *RC) {
129   return RC == &BF::AnyCCRegClass || BF::AnyCCRegClass.hasSubClass(RC);
130 }
131
132 static inline bool isDCC(const TargetRegisterClass *RC) {
133   return RC == &BF::DRegClass || BF::DRegClass.hasSubClass(RC) || isCC(RC);
134 }
135
136 static void UpdateNodeOperand(SelectionDAG &DAG,
137                               SDNode *N,
138                               unsigned Num,
139                               SDValue Val) {
140   SmallVector<SDValue, 8> ops(N->op_begin(), N->op_end());
141   ops[Num] = Val;
142   SDValue New = DAG.UpdateNodeOperands(SDValue(N, 0), ops.data(), ops.size());
143   DAG.ReplaceAllUsesWith(N, New.getNode());
144 }
145
146 // After instruction selection, insert COPY_TO_REGCLASS nodes to help in
147 // choosing the proper register classes.
148 void BlackfinDAGToDAGISel::FixRegisterClasses(SelectionDAG &DAG) {
149   const BlackfinInstrInfo &TII = getInstrInfo();
150   const BlackfinRegisterInfo *TRI = getRegisterInfo();
151   DAG.AssignTopologicalOrder();
152   HandleSDNode Dummy(DAG.getRoot());
153
154   for (SelectionDAG::allnodes_iterator NI = DAG.allnodes_begin();
155        NI != DAG.allnodes_end(); ++NI) {
156     if (NI->use_empty() || !NI->isMachineOpcode())
157       continue;
158     const TargetInstrDesc &DefTID = TII.get(NI->getMachineOpcode());
159     for (SDNode::use_iterator UI = NI->use_begin(); !UI.atEnd(); ++UI) {
160       if (!UI->isMachineOpcode())
161         continue;
162
163       if (UI.getUse().getResNo() >= DefTID.getNumDefs())
164         continue;
165       const TargetRegisterClass *DefRC =
166         DefTID.OpInfo[UI.getUse().getResNo()].getRegClass(TRI);
167
168       const TargetInstrDesc &UseTID = TII.get(UI->getMachineOpcode());
169       if (UseTID.getNumDefs()+UI.getOperandNo() >= UseTID.getNumOperands())
170         continue;
171       const TargetRegisterClass *UseRC =
172         UseTID.OpInfo[UseTID.getNumDefs()+UI.getOperandNo()].getRegClass(TRI);
173       if (!DefRC || !UseRC)
174         continue;
175       // We cannot copy CC <-> !(CC/D)
176       if ((isCC(DefRC) && !isDCC(UseRC)) || (isCC(UseRC) && !isDCC(DefRC))) {
177         SDNode *Copy =
178           DAG.getMachineNode(TargetOpcode::COPY_TO_REGCLASS,
179                              NI->getDebugLoc(),
180                              MVT::i32,
181                              UI.getUse().get(),
182                              DAG.getTargetConstant(BF::DRegClassID, MVT::i32));
183         UpdateNodeOperand(DAG, *UI, UI.getOperandNo(), SDValue(Copy, 0));
184       }
185     }
186   }
187   DAG.setRoot(Dummy.getValue());
188 }
189