|  | //===- BlackfinISelDAGToDAG.cpp - A dag to dag inst selector for Blackfin -===// | 
|  | // | 
|  | //                     The LLVM Compiler Infrastructure | 
|  | // | 
|  | // This file is distributed under the University of Illinois Open Source | 
|  | // License. See LICENSE.TXT for details. | 
|  | // | 
|  | //===----------------------------------------------------------------------===// | 
|  | // | 
|  | // This file defines an instruction selector for the Blackfin target. | 
|  | // | 
|  | //===----------------------------------------------------------------------===// | 
|  |  | 
|  | #include "Blackfin.h" | 
|  | #include "BlackfinTargetMachine.h" | 
|  | #include "BlackfinRegisterInfo.h" | 
|  | #include "llvm/Intrinsics.h" | 
|  | #include "llvm/CodeGen/SelectionDAGISel.h" | 
|  | #include "llvm/CodeGen/MachineRegisterInfo.h" | 
|  | #include "llvm/Support/Compiler.h" | 
|  | #include "llvm/Support/Debug.h" | 
|  | #include "llvm/Support/ErrorHandling.h" | 
|  | #include "llvm/Support/raw_ostream.h" | 
|  |  | 
|  | using namespace llvm; | 
|  |  | 
|  | //===----------------------------------------------------------------------===// | 
|  | // Instruction Selector Implementation | 
|  | //===----------------------------------------------------------------------===// | 
|  |  | 
|  | //===----------------------------------------------------------------------===// | 
|  | /// BlackfinDAGToDAGISel - Blackfin specific code to select blackfin machine | 
|  | /// instructions for SelectionDAG operations. | 
|  | namespace { | 
|  | class BlackfinDAGToDAGISel : public SelectionDAGISel { | 
|  | /// Subtarget - Keep a pointer to the Blackfin Subtarget around so that we | 
|  | /// can make the right decision when generating code for different targets. | 
|  | //const BlackfinSubtarget &Subtarget; | 
|  | public: | 
|  | BlackfinDAGToDAGISel(BlackfinTargetMachine &TM, CodeGenOpt::Level OptLevel) | 
|  | : SelectionDAGISel(TM, OptLevel) {} | 
|  |  | 
|  | virtual void PostprocessISelDAG(); | 
|  |  | 
|  | virtual const char *getPassName() const { | 
|  | return "Blackfin DAG->DAG Pattern Instruction Selection"; | 
|  | } | 
|  |  | 
|  | // Include the pieces autogenerated from the target description. | 
|  | #include "BlackfinGenDAGISel.inc" | 
|  |  | 
|  | private: | 
|  | SDNode *Select(SDNode *N); | 
|  | bool SelectADDRspii(SDValue Addr, SDValue &Base, SDValue &Offset); | 
|  |  | 
|  | // Walk the DAG after instruction selection, fixing register class issues. | 
|  | void FixRegisterClasses(SelectionDAG &DAG); | 
|  |  | 
|  | const BlackfinInstrInfo &getInstrInfo() { | 
|  | return *static_cast<const BlackfinTargetMachine&>(TM).getInstrInfo(); | 
|  | } | 
|  | const BlackfinRegisterInfo *getRegisterInfo() { | 
|  | return static_cast<const BlackfinTargetMachine&>(TM).getRegisterInfo(); | 
|  | } | 
|  | }; | 
|  | }  // end anonymous namespace | 
|  |  | 
|  | FunctionPass *llvm::createBlackfinISelDag(BlackfinTargetMachine &TM, | 
|  | CodeGenOpt::Level OptLevel) { | 
|  | return new BlackfinDAGToDAGISel(TM, OptLevel); | 
|  | } | 
|  |  | 
|  | void BlackfinDAGToDAGISel::PostprocessISelDAG() { | 
|  | FixRegisterClasses(*CurDAG); | 
|  | } | 
|  |  | 
|  | SDNode *BlackfinDAGToDAGISel::Select(SDNode *N) { | 
|  | if (N->isMachineOpcode()) | 
|  | return NULL;   // Already selected. | 
|  |  | 
|  | switch (N->getOpcode()) { | 
|  | default: break; | 
|  | case ISD::FrameIndex: { | 
|  | // Selects to ADDpp FI, 0 which in turn will become ADDimm7 SP, imm or ADDpp | 
|  | // SP, Px | 
|  | int FI = cast<FrameIndexSDNode>(N)->getIndex(); | 
|  | SDValue TFI = CurDAG->getTargetFrameIndex(FI, MVT::i32); | 
|  | return CurDAG->SelectNodeTo(N, BF::ADDpp, MVT::i32, TFI, | 
|  | CurDAG->getTargetConstant(0, MVT::i32)); | 
|  | } | 
|  | } | 
|  |  | 
|  | return SelectCode(N); | 
|  | } | 
|  |  | 
|  | bool BlackfinDAGToDAGISel::SelectADDRspii(SDValue Addr, | 
|  | SDValue &Base, | 
|  | SDValue &Offset) { | 
|  | FrameIndexSDNode *FIN = 0; | 
|  | if ((FIN = dyn_cast<FrameIndexSDNode>(Addr))) { | 
|  | Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), MVT::i32); | 
|  | Offset = CurDAG->getTargetConstant(0, MVT::i32); | 
|  | return true; | 
|  | } | 
|  | if (Addr.getOpcode() == ISD::ADD) { | 
|  | ConstantSDNode *CN = 0; | 
|  | if ((FIN = dyn_cast<FrameIndexSDNode>(Addr.getOperand(0))) && | 
|  | (CN = dyn_cast<ConstantSDNode>(Addr.getOperand(1))) && | 
|  | (CN->getSExtValue() % 4 == 0 && CN->getSExtValue() >= 0)) { | 
|  | // Constant positive word offset from frame index | 
|  | Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), MVT::i32); | 
|  | Offset = CurDAG->getTargetConstant(CN->getSExtValue(), MVT::i32); | 
|  | return true; | 
|  | } | 
|  | } | 
|  | return false; | 
|  | } | 
|  |  | 
|  | static inline bool isCC(const TargetRegisterClass *RC) { | 
|  | return BF::AnyCCRegClass.hasSubClassEq(RC); | 
|  | } | 
|  |  | 
|  | static inline bool isDCC(const TargetRegisterClass *RC) { | 
|  | return BF::DRegClass.hasSubClassEq(RC) || isCC(RC); | 
|  | } | 
|  |  | 
|  | static void UpdateNodeOperand(SelectionDAG &DAG, | 
|  | SDNode *N, | 
|  | unsigned Num, | 
|  | SDValue Val) { | 
|  | SmallVector<SDValue, 8> ops(N->op_begin(), N->op_end()); | 
|  | ops[Num] = Val; | 
|  | SDNode *New = DAG.UpdateNodeOperands(N, ops.data(), ops.size()); | 
|  | DAG.ReplaceAllUsesWith(N, New); | 
|  | } | 
|  |  | 
|  | // After instruction selection, insert COPY_TO_REGCLASS nodes to help in | 
|  | // choosing the proper register classes. | 
|  | void BlackfinDAGToDAGISel::FixRegisterClasses(SelectionDAG &DAG) { | 
|  | const BlackfinInstrInfo &TII = getInstrInfo(); | 
|  | const BlackfinRegisterInfo *TRI = getRegisterInfo(); | 
|  | DAG.AssignTopologicalOrder(); | 
|  | HandleSDNode Dummy(DAG.getRoot()); | 
|  |  | 
|  | for (SelectionDAG::allnodes_iterator NI = DAG.allnodes_begin(); | 
|  | NI != DAG.allnodes_end(); ++NI) { | 
|  | if (NI->use_empty() || !NI->isMachineOpcode()) | 
|  | continue; | 
|  | const MCInstrDesc &DefMCID = TII.get(NI->getMachineOpcode()); | 
|  | for (SDNode::use_iterator UI = NI->use_begin(); !UI.atEnd(); ++UI) { | 
|  | if (!UI->isMachineOpcode()) | 
|  | continue; | 
|  |  | 
|  | if (UI.getUse().getResNo() >= DefMCID.getNumDefs()) | 
|  | continue; | 
|  | const TargetRegisterClass *DefRC = | 
|  | TII.getRegClass(DefMCID, UI.getUse().getResNo(), TRI); | 
|  |  | 
|  | const MCInstrDesc &UseMCID = TII.get(UI->getMachineOpcode()); | 
|  | if (UseMCID.getNumDefs()+UI.getOperandNo() >= UseMCID.getNumOperands()) | 
|  | continue; | 
|  | const TargetRegisterClass *UseRC = | 
|  | TII.getRegClass(UseMCID, UseMCID.getNumDefs()+UI.getOperandNo(), TRI); | 
|  | if (!DefRC || !UseRC) | 
|  | continue; | 
|  | // We cannot copy CC <-> !(CC/D) | 
|  | if ((isCC(DefRC) && !isDCC(UseRC)) || (isCC(UseRC) && !isDCC(DefRC))) { | 
|  | SDNode *Copy = | 
|  | DAG.getMachineNode(TargetOpcode::COPY_TO_REGCLASS, | 
|  | NI->getDebugLoc(), | 
|  | MVT::i32, | 
|  | UI.getUse().get(), | 
|  | DAG.getTargetConstant(BF::DRegClassID, MVT::i32)); | 
|  | UpdateNodeOperand(DAG, *UI, UI.getOperandNo(), SDValue(Copy, 0)); | 
|  | } | 
|  | } | 
|  | } | 
|  | DAG.setRoot(Dummy.getValue()); | 
|  | } | 
|  |  |