1 //===- BlackfinISelDAGToDAG.cpp - A dag to dag inst selector for Blackfin -===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 // This file defines an instruction selector for the Blackfin target.
12 //===----------------------------------------------------------------------===//
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"
27 //===----------------------------------------------------------------------===//
28 // Instruction Selector Implementation
29 //===----------------------------------------------------------------------===//
31 //===----------------------------------------------------------------------===//
32 /// BlackfinDAGToDAGISel - Blackfin specific code to select blackfin machine
33 /// instructions for SelectionDAG operations.
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;
40 BlackfinDAGToDAGISel(BlackfinTargetMachine
&TM
, CodeGenOpt::Level OptLevel
)
41 : SelectionDAGISel(TM
, OptLevel
) {}
43 virtual void PostprocessISelDAG();
45 virtual const char *getPassName() const {
46 return "Blackfin DAG->DAG Pattern Instruction Selection";
49 // Include the pieces autogenerated from the target description.
50 #include "BlackfinGenDAGISel.inc"
53 SDNode
*Select(SDNode
*N
);
54 bool SelectADDRspii(SDValue Addr
, SDValue
&Base
, SDValue
&Offset
);
56 // Walk the DAG after instruction selection, fixing register class issues.
57 void FixRegisterClasses(SelectionDAG
&DAG
);
59 const BlackfinInstrInfo
&getInstrInfo() {
60 return *static_cast<const BlackfinTargetMachine
&>(TM
).getInstrInfo();
62 const BlackfinRegisterInfo
*getRegisterInfo() {
63 return static_cast<const BlackfinTargetMachine
&>(TM
).getRegisterInfo();
66 } // end anonymous namespace
68 FunctionPass
*llvm::createBlackfinISelDag(BlackfinTargetMachine
&TM
,
69 CodeGenOpt::Level OptLevel
) {
70 return new BlackfinDAGToDAGISel(TM
, OptLevel
);
73 void BlackfinDAGToDAGISel::PostprocessISelDAG() {
74 FixRegisterClasses(*CurDAG
);
77 SDNode
*BlackfinDAGToDAGISel::Select(SDNode
*N
) {
78 if (N
->isMachineOpcode())
79 return NULL
; // Already selected.
81 switch (N
->getOpcode()) {
83 case ISD::FrameIndex
: {
84 // Selects to ADDpp FI, 0 which in turn will become ADDimm7 SP, imm or ADDpp
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
));
96 bool BlackfinDAGToDAGISel::SelectADDRspii(SDValue Addr
,
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
);
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
);
119 static inline bool isCC(const TargetRegisterClass
*RC
) {
120 return BF::AnyCCRegClass
.hasSubClassEq(RC
);
123 static inline bool isDCC(const TargetRegisterClass
*RC
) {
124 return BF::DRegClass
.hasSubClassEq(RC
) || isCC(RC
);
127 static void UpdateNodeOperand(SelectionDAG
&DAG
,
131 SmallVector
<SDValue
, 8> ops(N
->op_begin(), N
->op_end());
133 SDNode
*New
= DAG
.UpdateNodeOperands(N
, ops
.data(), ops
.size());
134 DAG
.ReplaceAllUsesWith(N
, New
);
137 // After instruction selection, insert COPY_TO_REGCLASS nodes to help in
138 // choosing the proper register classes.
139 void BlackfinDAGToDAGISel::FixRegisterClasses(SelectionDAG
&DAG
) {
140 const BlackfinInstrInfo
&TII
= getInstrInfo();
141 const BlackfinRegisterInfo
*TRI
= getRegisterInfo();
142 DAG
.AssignTopologicalOrder();
143 HandleSDNode
Dummy(DAG
.getRoot());
145 for (SelectionDAG::allnodes_iterator NI
= DAG
.allnodes_begin();
146 NI
!= DAG
.allnodes_end(); ++NI
) {
147 if (NI
->use_empty() || !NI
->isMachineOpcode())
149 const MCInstrDesc
&DefMCID
= TII
.get(NI
->getMachineOpcode());
150 for (SDNode::use_iterator UI
= NI
->use_begin(); !UI
.atEnd(); ++UI
) {
151 if (!UI
->isMachineOpcode())
154 if (UI
.getUse().getResNo() >= DefMCID
.getNumDefs())
156 const TargetRegisterClass
*DefRC
=
157 TII
.getRegClass(DefMCID
, UI
.getUse().getResNo(), TRI
);
159 const MCInstrDesc
&UseMCID
= TII
.get(UI
->getMachineOpcode());
160 if (UseMCID
.getNumDefs()+UI
.getOperandNo() >= UseMCID
.getNumOperands())
162 const TargetRegisterClass
*UseRC
=
163 TII
.getRegClass(UseMCID
, UseMCID
.getNumDefs()+UI
.getOperandNo(), TRI
);
164 if (!DefRC
|| !UseRC
)
166 // We cannot copy CC <-> !(CC/D)
167 if ((isCC(DefRC
) && !isDCC(UseRC
)) || (isCC(UseRC
) && !isDCC(DefRC
))) {
169 DAG
.getMachineNode(TargetOpcode::COPY_TO_REGCLASS
,
173 DAG
.getTargetConstant(BF::DRegClassID
, MVT::i32
));
174 UpdateNodeOperand(DAG
, *UI
, UI
.getOperandNo(), SDValue(Copy
, 0));
178 DAG
.setRoot(Dummy
.getValue());