//===-- TeakISelDAGToDAG.cpp - A dag to dag inst selector for Teak ------===// // // 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 Teak target. // //===----------------------------------------------------------------------===// #include "Teak.h" #include "TeakTargetMachine.h" #include "llvm/CodeGen/SelectionDAGISel.h" #include "llvm/Support/Compiler.h" #include "llvm/Support/Debug.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/raw_ostream.h" #include "TeakInstrInfo.h" using namespace llvm; /// TeakDAGToDAGISel - Teak specific code to select Teak machine /// instructions for SelectionDAG operations. /// namespace { class TeakDAGToDAGISel : public SelectionDAGISel { const TeakSubtarget &Subtarget; public: explicit TeakDAGToDAGISel(TeakTargetMachine &TM, CodeGenOpt::Level OptLevel) : SelectionDAGISel(TM, OptLevel), Subtarget(*TM.getSubtargetImpl()) {} void Select(SDNode *N) override; bool SelectAddr(SDValue Addr, SDValue &Base, SDValue &Offset); virtual StringRef getPassName() const override { return "Teak DAG->DAG Pattern Instruction Selection"; } private: // SDNode *SelectMoveImmediate(SDNode *N); // SDNode *SelectConditionalBranch(SDNode *N); bool SelectLoad(SDNode* N); //bool SelectBRICC(SDNode* node); // Include the pieces autogenerated from the target description. #include "TeakGenDAGISel.inc" }; } // end anonymous namespace bool TeakDAGToDAGISel::SelectAddr(SDValue Addr, SDValue &Base, SDValue& Offset) { dbgs() << "TeakDAGToDAGISel::SelectAddr: " << Addr.getOpcode() << "\n"; if (FrameIndexSDNode *FIN = dyn_cast(Addr)) { EVT PtrVT = getTargetLowering()->getPointerTy(CurDAG->getDataLayout()); Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), PtrVT); Offset = CurDAG->getTargetConstant(0, Addr, MVT::i16); return true; } return false; // if (Addr.getOpcode() == ISD::TargetExternalSymbol || // Addr.getOpcode() == ISD::TargetGlobalAddress || // Addr.getOpcode() == ISD::TargetGlobalTLSAddress) // { // return false; // direct calls. // } // Base = Addr; // Offset = CurDAG->getTargetConstant(0, Addr, MVT::i16); // return true; } // SDNode *TeakDAGToDAGISel::SelectMoveImmediate(SDNode *N) { // // Make sure the immediate size is supported. // ConstantSDNode *ConstVal = cast(N); // uint64_t ImmVal = ConstVal->getZExtValue(); // uint64_t SupportedMask = 0xfffffffff; // if ((ImmVal & SupportedMask) != ImmVal) { // return SelectCode(N); // } // // Select the low part of the immediate move. // uint64_t LoMask = 0xffff; // uint64_t HiMask = 0xffff0000; // uint64_t ImmLo = (ImmVal & LoMask); // uint64_t ImmHi = (ImmVal & HiMask); // SDValue ConstLo = CurDAG->getTargetConstant(ImmLo, N, MVT::i32); // MachineSDNode *Move = // CurDAG->getMachineNode(Teak::MOVLOi16, N, MVT::i32, ConstLo); // // Select the low part of the immediate move, if needed. // if (ImmHi) { // SDValue ConstHi = CurDAG->getTargetConstant(ImmHi >> 16, N, MVT::i32); // Move = CurDAG->getMachineNode(Teak::MOVHIi16, N, MVT::i32, SDValue(Move, // 0), // ConstHi); // } // return Move; // } // SDNode *TeakDAGToDAGISel::SelectConditionalBranch(SDNode *N) { // SDValue Chain = N->getOperand(0); // SDValue Cond = N->getOperand(1); // SDValue LHS = N->getOperand(2); // SDValue RHS = N->getOperand(3); // SDValue Target = N->getOperand(4); // // Generate a comparison instruction. // EVT CompareTys[] = { MVT::Other, MVT::Glue }; // SDVTList CompareVT = CurDAG->getVTList(CompareTys); // SDValue CompareOps[] = {LHS, RHS, Chain}; // SDNode *Compare = CurDAG->getMachineNode(Teak::CMP, N, CompareVT, // CompareOps); // // Generate a predicated branch instruction. // CondCodeSDNode *CC = cast(Cond.getNode()); // SDValue CCVal = CurDAG->getTargetConstant(CC->get(), N, MVT::i32); // SDValue BranchOps[] = {CCVal, Target, SDValue(Compare, 0), // SDValue(Compare, 1)}; // return CurDAG->getMachineNode(Teak::Bcc, N, MVT::Other, BranchOps); // } bool TeakDAGToDAGISel::SelectLoad(SDNode* node) { dbgs() << "TeakDAGToDAGISel::SelectLoad\n"; const LoadSDNode* ld = cast(node); ISD::MemIndexedMode idxMode = ld->getAddressingMode(); MVT vType = ld->getMemoryVT().getSimpleVT(); //ld->dump(); dbgs() << "mode: " << idxMode << "\n"; if(idxMode != ISD::POST_INC && idxMode != ISD::POST_DEC) return false; int offs = cast(ld->getOffset())->getSExtValue(); dbgs() << "offset: " << offs << "\n"; return false; } // bool TeakDAGToDAGISel::SelectBRICC(SDNode* node) // { // SDValue dst = node->getOperand(0); // SDValue cond = node->getOperand(1); // SDValue shit = node->getOperand(2); // SDValue branchOps[] = { dst, cond, CurDAG->getRegister(Teak::ICC, MVT::i32), shit }; // SDNode* resNode = CurDAG->getMachineNode(Teak::BRR_rel7, node, MVT::Other, branchOps); // ReplaceUses(SDValue(node, 0), SDValue(resNode, 0)); // CurDAG->RemoveDeadNode(node); // return true; // } void TeakDAGToDAGISel::Select(SDNode* N) { switch (N->getOpcode()) { case ISD::LOAD: if(SelectLoad(N)) return; break; // case TeakISD::BRICC: // if(SelectBRICC(N)) // return; // break; } // if (N->isMachineOpcode()) { // N->setNodeId(-1); // return; // Already selected. // } // if(N->getOpcode() == TeakISD::RET_FLAG) // { // SelectCode(N); // return; // } // else if(N->getOpcode() == ISD::FrameIndex) // { // } // N->dump(); // dbgs() << "opcode: " << N->getOpcode() << "\n"; //llvm_unreachable("Unimplemented TeakDAGToDAGISel::Select"); SelectCode(N); } /// createTeakISelDag - This pass converts a legalized DAG into a /// Teak-specific DAG, ready for instruction scheduling. /// FunctionPass *llvm::createTeakISelDag(TeakTargetMachine &TM, CodeGenOpt::Level OptLevel) { return new TeakDAGToDAGISel(TM, OptLevel); }