• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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:
BlackfinDAGToDAGISel(BlackfinTargetMachine & TM,CodeGenOpt::Level OptLevel)40     BlackfinDAGToDAGISel(BlackfinTargetMachine &TM, CodeGenOpt::Level OptLevel)
41       : SelectionDAGISel(TM, OptLevel) {}
42 
43     virtual void PostprocessISelDAG();
44 
getPassName() const45     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(SDValue Addr, SDValue &Base, SDValue &Offset);
55 
56     // Walk the DAG after instruction selection, fixing register class issues.
57     void FixRegisterClasses(SelectionDAG &DAG);
58 
getInstrInfo()59     const BlackfinInstrInfo &getInstrInfo() {
60       return *static_cast<const BlackfinTargetMachine&>(TM).getInstrInfo();
61     }
getRegisterInfo()62     const BlackfinRegisterInfo *getRegisterInfo() {
63       return static_cast<const BlackfinTargetMachine&>(TM).getRegisterInfo();
64     }
65   };
66 }  // end anonymous namespace
67 
createBlackfinISelDag(BlackfinTargetMachine & TM,CodeGenOpt::Level OptLevel)68 FunctionPass *llvm::createBlackfinISelDag(BlackfinTargetMachine &TM,
69                                           CodeGenOpt::Level OptLevel) {
70   return new BlackfinDAGToDAGISel(TM, OptLevel);
71 }
72 
PostprocessISelDAG()73 void BlackfinDAGToDAGISel::PostprocessISelDAG() {
74   FixRegisterClasses(*CurDAG);
75 }
76 
Select(SDNode * N)77 SDNode *BlackfinDAGToDAGISel::Select(SDNode *N) {
78   if (N->isMachineOpcode())
79     return NULL;   // Already selected.
80 
81   switch (N->getOpcode()) {
82   default: break;
83   case ISD::FrameIndex: {
84     // Selects to ADDpp FI, 0 which in turn will become ADDimm7 SP, imm or ADDpp
85     // SP, Px
86     int FI = cast<FrameIndexSDNode>(N)->getIndex();
87     SDValue TFI = CurDAG->getTargetFrameIndex(FI, MVT::i32);
88     return CurDAG->SelectNodeTo(N, BF::ADDpp, MVT::i32, TFI,
89                                 CurDAG->getTargetConstant(0, MVT::i32));
90   }
91   }
92 
93   return SelectCode(N);
94 }
95 
SelectADDRspii(SDValue Addr,SDValue & Base,SDValue & Offset)96 bool BlackfinDAGToDAGISel::SelectADDRspii(SDValue Addr,
97                                           SDValue &Base,
98                                           SDValue &Offset) {
99   FrameIndexSDNode *FIN = 0;
100   if ((FIN = dyn_cast<FrameIndexSDNode>(Addr))) {
101     Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), MVT::i32);
102     Offset = CurDAG->getTargetConstant(0, MVT::i32);
103     return true;
104   }
105   if (Addr.getOpcode() == ISD::ADD) {
106     ConstantSDNode *CN = 0;
107     if ((FIN = dyn_cast<FrameIndexSDNode>(Addr.getOperand(0))) &&
108         (CN = dyn_cast<ConstantSDNode>(Addr.getOperand(1))) &&
109         (CN->getSExtValue() % 4 == 0 && CN->getSExtValue() >= 0)) {
110       // Constant positive word offset from frame index
111       Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), MVT::i32);
112       Offset = CurDAG->getTargetConstant(CN->getSExtValue(), MVT::i32);
113       return true;
114     }
115   }
116   return false;
117 }
118 
isCC(const TargetRegisterClass * RC)119 static inline bool isCC(const TargetRegisterClass *RC) {
120   return BF::AnyCCRegClass.hasSubClassEq(RC);
121 }
122 
isDCC(const TargetRegisterClass * RC)123 static inline bool isDCC(const TargetRegisterClass *RC) {
124   return BF::DRegClass.hasSubClassEq(RC) || isCC(RC);
125 }
126 
UpdateNodeOperand(SelectionDAG & DAG,SDNode * N,unsigned Num,SDValue Val)127 static void UpdateNodeOperand(SelectionDAG &DAG,
128                               SDNode *N,
129                               unsigned Num,
130                               SDValue Val) {
131   SmallVector<SDValue, 8> ops(N->op_begin(), N->op_end());
132   ops[Num] = Val;
133   SDNode *New = DAG.UpdateNodeOperands(N, ops.data(), ops.size());
134   DAG.ReplaceAllUsesWith(N, New);
135 }
136 
137 // After instruction selection, insert COPY_TO_REGCLASS nodes to help in
138 // choosing the proper register classes.
FixRegisterClasses(SelectionDAG & DAG)139 void BlackfinDAGToDAGISel::FixRegisterClasses(SelectionDAG &DAG) {
140   const BlackfinInstrInfo &TII = getInstrInfo();
141   const BlackfinRegisterInfo *TRI = getRegisterInfo();
142   DAG.AssignTopologicalOrder();
143   HandleSDNode Dummy(DAG.getRoot());
144 
145   for (SelectionDAG::allnodes_iterator NI = DAG.allnodes_begin();
146        NI != DAG.allnodes_end(); ++NI) {
147     if (NI->use_empty() || !NI->isMachineOpcode())
148       continue;
149     const MCInstrDesc &DefMCID = TII.get(NI->getMachineOpcode());
150     for (SDNode::use_iterator UI = NI->use_begin(); !UI.atEnd(); ++UI) {
151       if (!UI->isMachineOpcode())
152         continue;
153 
154       if (UI.getUse().getResNo() >= DefMCID.getNumDefs())
155         continue;
156       const TargetRegisterClass *DefRC =
157         TII.getRegClass(DefMCID, UI.getUse().getResNo(), TRI);
158 
159       const MCInstrDesc &UseMCID = TII.get(UI->getMachineOpcode());
160       if (UseMCID.getNumDefs()+UI.getOperandNo() >= UseMCID.getNumOperands())
161         continue;
162       const TargetRegisterClass *UseRC =
163         TII.getRegClass(UseMCID, UseMCID.getNumDefs()+UI.getOperandNo(), TRI);
164       if (!DefRC || !UseRC)
165         continue;
166       // We cannot copy CC <-> !(CC/D)
167       if ((isCC(DefRC) && !isDCC(UseRC)) || (isCC(UseRC) && !isDCC(DefRC))) {
168         SDNode *Copy =
169           DAG.getMachineNode(TargetOpcode::COPY_TO_REGCLASS,
170                              NI->getDebugLoc(),
171                              MVT::i32,
172                              UI.getUse().get(),
173                              DAG.getTargetConstant(BF::DRegClassID, MVT::i32));
174         UpdateNodeOperand(DAG, *UI, UI.getOperandNo(), SDValue(Copy, 0));
175       }
176     }
177   }
178   DAG.setRoot(Dummy.getValue());
179 }
180 
181