llvm-6502/lib/Target/XCore/XCoreISelDAGToDAG.cpp
Dan Gohman 602b0c8c17 Rename getTargetNode to getMachineNode, for consistency with the
naming scheme used in SelectionDAG, where there are multiple kinds
of "target" nodes, but "machine" nodes are nodes which represent
a MachineInstr.


git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@82790 91177308-0d34-0410-b5e6-96231b3b80d8
2009-09-25 18:54:59 +00:00

236 lines
8.4 KiB
C++

//===-- XCoreISelDAGToDAG.cpp - A dag to dag inst selector for XCore ------===//
//
// 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 XCore target.
//
//===----------------------------------------------------------------------===//
#include "XCore.h"
#include "XCoreISelLowering.h"
#include "XCoreTargetMachine.h"
#include "llvm/DerivedTypes.h"
#include "llvm/Function.h"
#include "llvm/Intrinsics.h"
#include "llvm/CallingConv.h"
#include "llvm/Constants.h"
#include "llvm/LLVMContext.h"
#include "llvm/CodeGen/MachineFrameInfo.h"
#include "llvm/CodeGen/MachineFunction.h"
#include "llvm/CodeGen/MachineInstrBuilder.h"
#include "llvm/CodeGen/MachineRegisterInfo.h"
#include "llvm/CodeGen/SelectionDAG.h"
#include "llvm/CodeGen/SelectionDAGISel.h"
#include "llvm/Target/TargetLowering.h"
#include "llvm/Support/Compiler.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/raw_ostream.h"
#include <queue>
#include <set>
using namespace llvm;
/// XCoreDAGToDAGISel - XCore specific code to select XCore machine
/// instructions for SelectionDAG operations.
///
namespace {
class XCoreDAGToDAGISel : public SelectionDAGISel {
XCoreTargetLowering &Lowering;
const XCoreSubtarget &Subtarget;
public:
XCoreDAGToDAGISel(XCoreTargetMachine &TM)
: SelectionDAGISel(TM),
Lowering(*TM.getTargetLowering()),
Subtarget(*TM.getSubtargetImpl()) { }
SDNode *Select(SDValue Op);
/// getI32Imm - Return a target constant with the specified value, of type
/// i32.
inline SDValue getI32Imm(unsigned Imm) {
return CurDAG->getTargetConstant(Imm, MVT::i32);
}
// Complex Pattern Selectors.
bool SelectADDRspii(SDValue Op, SDValue Addr, SDValue &Base,
SDValue &Offset);
bool SelectADDRdpii(SDValue Op, SDValue Addr, SDValue &Base,
SDValue &Offset);
bool SelectADDRcpii(SDValue Op, SDValue Addr, SDValue &Base,
SDValue &Offset);
virtual void InstructionSelect();
virtual const char *getPassName() const {
return "XCore DAG->DAG Pattern Instruction Selection";
}
// Include the pieces autogenerated from the target description.
#include "XCoreGenDAGISel.inc"
};
} // end anonymous namespace
/// createXCoreISelDag - This pass converts a legalized DAG into a
/// XCore-specific DAG, ready for instruction scheduling.
///
FunctionPass *llvm::createXCoreISelDag(XCoreTargetMachine &TM) {
return new XCoreDAGToDAGISel(TM);
}
bool XCoreDAGToDAGISel::SelectADDRspii(SDValue Op, 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;
}
bool XCoreDAGToDAGISel::SelectADDRdpii(SDValue Op, SDValue Addr,
SDValue &Base, SDValue &Offset) {
if (Addr.getOpcode() == XCoreISD::DPRelativeWrapper) {
Base = Addr.getOperand(0);
Offset = CurDAG->getTargetConstant(0, MVT::i32);
return true;
}
if (Addr.getOpcode() == ISD::ADD) {
ConstantSDNode *CN = 0;
if ((Addr.getOperand(0).getOpcode() == XCoreISD::DPRelativeWrapper)
&& (CN = dyn_cast<ConstantSDNode>(Addr.getOperand(1)))
&& (CN->getSExtValue() % 4 == 0)) {
// Constant word offset from a object in the data region
Base = Addr.getOperand(0).getOperand(0);
Offset = CurDAG->getTargetConstant(CN->getSExtValue(), MVT::i32);
return true;
}
}
return false;
}
bool XCoreDAGToDAGISel::SelectADDRcpii(SDValue Op, SDValue Addr,
SDValue &Base, SDValue &Offset) {
if (Addr.getOpcode() == XCoreISD::CPRelativeWrapper) {
Base = Addr.getOperand(0);
Offset = CurDAG->getTargetConstant(0, MVT::i32);
return true;
}
if (Addr.getOpcode() == ISD::ADD) {
ConstantSDNode *CN = 0;
if ((Addr.getOperand(0).getOpcode() == XCoreISD::CPRelativeWrapper)
&& (CN = dyn_cast<ConstantSDNode>(Addr.getOperand(1)))
&& (CN->getSExtValue() % 4 == 0)) {
// Constant word offset from a object in the data region
Base = Addr.getOperand(0).getOperand(0);
Offset = CurDAG->getTargetConstant(CN->getSExtValue(), MVT::i32);
return true;
}
}
return false;
}
/// InstructionSelect - This callback is invoked by
/// SelectionDAGISel when it has created a SelectionDAG for us to codegen.
void XCoreDAGToDAGISel::
InstructionSelect() {
DEBUG(BB->dump());
// Select target instructions for the DAG.
SelectRoot(*CurDAG);
CurDAG->RemoveDeadNodes();
}
SDNode *XCoreDAGToDAGISel::Select(SDValue Op) {
SDNode *N = Op.getNode();
DebugLoc dl = N->getDebugLoc();
EVT NVT = N->getValueType(0);
if (NVT == MVT::i32) {
switch (N->getOpcode()) {
default: break;
case ISD::Constant: {
if (Predicate_immMskBitp(N)) {
SDValue MskSize = Transform_msksize_xform(N);
return CurDAG->getMachineNode(XCore::MKMSK_rus, dl,
MVT::i32, MskSize);
}
else if (! Predicate_immU16(N)) {
unsigned Val = cast<ConstantSDNode>(N)->getZExtValue();
SDValue CPIdx =
CurDAG->getTargetConstantPool(ConstantInt::get(
Type::getInt32Ty(*CurDAG->getContext()), Val),
TLI.getPointerTy());
return CurDAG->getMachineNode(XCore::LDWCP_lru6, dl, MVT::i32,
MVT::Other, CPIdx,
CurDAG->getEntryNode());
}
break;
}
case ISD::SMUL_LOHI: {
// FIXME fold addition into the macc instruction
if (!Subtarget.isXS1A()) {
SDValue Zero(CurDAG->getMachineNode(XCore::LDC_ru6, dl, MVT::i32,
CurDAG->getTargetConstant(0, MVT::i32)), 0);
SDValue Ops[] = { Zero, Zero, Op.getOperand(0), Op.getOperand(1) };
SDNode *ResNode = CurDAG->getMachineNode(XCore::MACCS_l4r, dl,
MVT::i32, MVT::i32, Ops, 4);
ReplaceUses(SDValue(N, 0), SDValue(ResNode, 1));
ReplaceUses(SDValue(N, 1), SDValue(ResNode, 0));
return NULL;
}
break;
}
case ISD::UMUL_LOHI: {
// FIXME fold addition into the macc / lmul instruction
SDValue Zero(CurDAG->getMachineNode(XCore::LDC_ru6, dl, MVT::i32,
CurDAG->getTargetConstant(0, MVT::i32)), 0);
SDValue Ops[] = { Op.getOperand(0), Op.getOperand(1),
Zero, Zero };
SDNode *ResNode = CurDAG->getMachineNode(XCore::LMUL_l6r, dl, MVT::i32,
MVT::i32, Ops, 4);
ReplaceUses(SDValue(N, 0), SDValue(ResNode, 1));
ReplaceUses(SDValue(N, 1), SDValue(ResNode, 0));
return NULL;
}
case XCoreISD::LADD: {
if (!Subtarget.isXS1A()) {
SDValue Ops[] = { Op.getOperand(0), Op.getOperand(1),
Op.getOperand(2) };
return CurDAG->getMachineNode(XCore::LADD_l5r, dl, MVT::i32, MVT::i32,
Ops, 3);
}
break;
}
case XCoreISD::LSUB: {
if (!Subtarget.isXS1A()) {
SDValue Ops[] = { Op.getOperand(0), Op.getOperand(1),
Op.getOperand(2) };
return CurDAG->getMachineNode(XCore::LSUB_l5r, dl, MVT::i32, MVT::i32,
Ops, 3);
}
break;
}
// Other cases are autogenerated.
}
}
return SelectCode(Op);
}