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