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 "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"
28 //===----------------------------------------------------------------------===//
29 // Instruction Selector Implementation
30 //===----------------------------------------------------------------------===//
32 //===----------------------------------------------------------------------===//
33 /// BlackfinDAGToDAGISel - Blackfin specific code to select blackfin machine
34 /// instructions for SelectionDAG operations.
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;
41 BlackfinDAGToDAGISel(BlackfinTargetMachine &TM, CodeGenOpt::Level OptLevel)
42 : SelectionDAGISel(TM, OptLevel) {}
44 virtual void InstructionSelect();
46 virtual const char *getPassName() const {
47 return "Blackfin DAG->DAG Pattern Instruction Selection";
50 // Include the pieces autogenerated from the target description.
51 #include "BlackfinGenDAGISel.inc"
54 SDNode *Select(SDValue Op);
55 bool SelectADDRspii(SDValue Op, SDValue Addr,
56 SDValue &Base, SDValue &Offset);
58 // Walk the DAG after instruction selection, fixing register class issues.
59 void FixRegisterClasses(SelectionDAG &DAG);
61 const BlackfinInstrInfo &getInstrInfo() {
62 return *static_cast<const BlackfinTargetMachine&>(TM).getInstrInfo();
64 const BlackfinRegisterInfo *getRegisterInfo() {
65 return static_cast<const BlackfinTargetMachine&>(TM).getRegisterInfo();
68 } // end anonymous namespace
70 FunctionPass *llvm::createBlackfinISelDag(BlackfinTargetMachine &TM,
71 CodeGenOpt::Level OptLevel) {
72 return new BlackfinDAGToDAGISel(TM, OptLevel);
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.
80 DEBUG(errs() << "Selected selection DAG before regclass fixup:\n");
81 DEBUG(CurDAG->dump());
82 FixRegisterClasses(*CurDAG);
85 SDNode *BlackfinDAGToDAGISel::Select(SDValue Op) {
86 SDNode *N = Op.getNode();
87 DebugLoc dl = N->getDebugLoc();
88 if (N->isMachineOpcode())
89 return NULL; // Already selected.
91 switch (N->getOpcode()) {
93 case ISD::FrameIndex: {
94 // Selects to ADDpp FI, 0 which in turn will become ADDimm7 SP, imm or ADDpp
96 int FI = cast<FrameIndexSDNode>(N)->getIndex();
97 SDValue TFI = CurDAG->getTargetFrameIndex(FI, MVT::i32);
98 return CurDAG->SelectNodeTo(N, BF::ADDpp, MVT::i32, TFI,
99 CurDAG->getTargetConstant(0, MVT::i32));
103 return SelectCode(Op);
106 bool BlackfinDAGToDAGISel::SelectADDRspii(SDValue Op,
110 FrameIndexSDNode *FIN = 0;
111 if ((FIN = dyn_cast<FrameIndexSDNode>(Addr))) {
112 Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), MVT::i32);
113 Offset = CurDAG->getTargetConstant(0, MVT::i32);
116 if (Addr.getOpcode() == ISD::ADD) {
117 ConstantSDNode *CN = 0;
118 if ((FIN = dyn_cast<FrameIndexSDNode>(Addr.getOperand(0))) &&
119 (CN = dyn_cast<ConstantSDNode>(Addr.getOperand(1))) &&
120 (CN->getSExtValue() % 4 == 0 && CN->getSExtValue() >= 0)) {
121 // Constant positive word offset from frame index
122 Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), MVT::i32);
123 Offset = CurDAG->getTargetConstant(CN->getSExtValue(), MVT::i32);
130 static inline bool isCC(const TargetRegisterClass *RC) {
131 return RC == &BF::AnyCCRegClass || BF::AnyCCRegClass.hasSubClass(RC);
134 static inline bool isDCC(const TargetRegisterClass *RC) {
135 return RC == &BF::DRegClass || BF::DRegClass.hasSubClass(RC) || isCC(RC);
138 static void UpdateNodeOperand(SelectionDAG &DAG,
142 SmallVector<SDValue, 8> ops(N->op_begin(), N->op_end());
144 SDValue New = DAG.UpdateNodeOperands(SDValue(N, 0), ops.data(), ops.size());
145 DAG.ReplaceAllUsesWith(N, New.getNode());
148 // After instruction selection, insert COPY_TO_REGCLASS nodes to help in
149 // choosing the proper register classes.
150 void BlackfinDAGToDAGISel::FixRegisterClasses(SelectionDAG &DAG) {
151 const BlackfinInstrInfo &TII = getInstrInfo();
152 const BlackfinRegisterInfo *TRI = getRegisterInfo();
153 DAG.AssignTopologicalOrder();
154 HandleSDNode Dummy(DAG.getRoot());
156 for (SelectionDAG::allnodes_iterator NI = DAG.allnodes_begin();
157 NI != DAG.allnodes_end(); ++NI) {
158 if (NI->use_empty() || !NI->isMachineOpcode())
160 const TargetInstrDesc &DefTID = TII.get(NI->getMachineOpcode());
161 for (SDNode::use_iterator UI = NI->use_begin(); !UI.atEnd(); ++UI) {
162 if (!UI->isMachineOpcode())
165 if (UI.getUse().getResNo() >= DefTID.getNumDefs())
167 const TargetRegisterClass *DefRC =
168 DefTID.OpInfo[UI.getUse().getResNo()].getRegClass(TRI);
170 const TargetInstrDesc &UseTID = TII.get(UI->getMachineOpcode());
171 if (UseTID.getNumDefs()+UI.getOperandNo() >= UseTID.getNumOperands())
173 const TargetRegisterClass *UseRC =
174 UseTID.OpInfo[UseTID.getNumDefs()+UI.getOperandNo()].getRegClass(TRI);
175 if (!DefRC || !UseRC)
177 // We cannot copy CC <-> !(CC/D)
178 if ((isCC(DefRC) && !isDCC(UseRC)) || (isCC(UseRC) && !isDCC(DefRC))) {
180 DAG.getMachineNode(TargetInstrInfo::COPY_TO_REGCLASS,
184 DAG.getTargetConstant(BF::DRegClassID, MVT::i32));
185 UpdateNodeOperand(DAG, *UI, UI.getOperandNo(), SDValue(Copy, 0));
189 DAG.setRoot(Dummy.getValue());