teak-llvm/llvm/lib/Target/Teak/TeakISelDAGToDAG.cpp

199 lines
6.5 KiB
C++

//===-- 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<FrameIndexSDNode>(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<ConstantSDNode>(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<CondCodeSDNode>(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<LoadSDNode>(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<ConstantSDNode>(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);
}