| //===- 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()); |
| } |
| |