LLVM API Documentation

XCoreISelDAGToDAG.cpp

Go to the documentation of this file.
00001 //===-- XCoreISelDAGToDAG.cpp - A dag to dag inst selector for XCore ------===//
00002 //
00003 //                     The LLVM Compiler Infrastructure
00004 //
00005 // This file is distributed under the University of Illinois Open Source
00006 // License. See LICENSE.TXT for details.
00007 //
00008 //===----------------------------------------------------------------------===//
00009 //
00010 // This file defines an instruction selector for the XCore target.
00011 //
00012 //===----------------------------------------------------------------------===//
00013 
00014 #include "XCore.h"
00015 #include "XCoreISelLowering.h"
00016 #include "XCoreTargetMachine.h"
00017 #include "llvm/DerivedTypes.h"
00018 #include "llvm/Function.h"
00019 #include "llvm/Intrinsics.h"
00020 #include "llvm/CallingConv.h"
00021 #include "llvm/Constants.h"
00022 #include "llvm/CodeGen/MachineFrameInfo.h"
00023 #include "llvm/CodeGen/MachineFunction.h"
00024 #include "llvm/CodeGen/MachineInstrBuilder.h"
00025 #include "llvm/CodeGen/MachineRegisterInfo.h"
00026 #include "llvm/CodeGen/SelectionDAG.h"
00027 #include "llvm/CodeGen/SelectionDAGISel.h"
00028 #include "llvm/Target/TargetLowering.h"
00029 #include "llvm/Support/Compiler.h"
00030 #include "llvm/Support/Debug.h"
00031 #include <queue>
00032 #include <set>
00033 using namespace llvm;
00034 
00035 /// XCoreDAGToDAGISel - XCore specific code to select XCore machine
00036 /// instructions for SelectionDAG operations.
00037 ///
00038 namespace {
00039   class XCoreDAGToDAGISel : public SelectionDAGISel {
00040     XCoreTargetLowering &Lowering;
00041     const XCoreSubtarget &Subtarget;
00042 
00043   public:
00044     XCoreDAGToDAGISel(XCoreTargetMachine &TM)
00045       : SelectionDAGISel(TM),
00046         Lowering(*TM.getTargetLowering()), 
00047         Subtarget(*TM.getSubtargetImpl()) { }
00048 
00049     SDNode *Select(SDValue Op);
00050     
00051     /// getI32Imm - Return a target constant with the specified value, of type
00052     /// i32.
00053     inline SDValue getI32Imm(unsigned Imm) {
00054       return CurDAG->getTargetConstant(Imm, MVT::i32);
00055     }
00056 
00057     // Complex Pattern Selectors.
00058     bool SelectADDRspii(SDValue Op, SDValue Addr, SDValue &Base,
00059                         SDValue &Offset);
00060     bool SelectADDRdpii(SDValue Op, SDValue Addr, SDValue &Base,
00061                         SDValue &Offset);
00062     bool SelectADDRcpii(SDValue Op, SDValue Addr, SDValue &Base,
00063                         SDValue &Offset);
00064     
00065     virtual void InstructionSelect();
00066 
00067     virtual const char *getPassName() const {
00068       return "XCore DAG->DAG Pattern Instruction Selection";
00069     } 
00070     
00071     // Include the pieces autogenerated from the target description.
00072   #include "XCoreGenDAGISel.inc"
00073   };
00074 }  // end anonymous namespace
00075 
00076 /// createXCoreISelDag - This pass converts a legalized DAG into a 
00077 /// XCore-specific DAG, ready for instruction scheduling.
00078 ///
00079 FunctionPass *llvm::createXCoreISelDag(XCoreTargetMachine &TM) {
00080   return new XCoreDAGToDAGISel(TM);
00081 }
00082 
00083 bool XCoreDAGToDAGISel::SelectADDRspii(SDValue Op, SDValue Addr,
00084                                   SDValue &Base, SDValue &Offset) {
00085   FrameIndexSDNode *FIN = 0;
00086   if ((FIN = dyn_cast<FrameIndexSDNode>(Addr))) {
00087     Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), MVT::i32);
00088     Offset = CurDAG->getTargetConstant(0, MVT::i32);
00089     return true;
00090   }
00091   if (Addr.getOpcode() == ISD::ADD) {
00092     ConstantSDNode *CN = 0;
00093     if ((FIN = dyn_cast<FrameIndexSDNode>(Addr.getOperand(0)))
00094       && (CN = dyn_cast<ConstantSDNode>(Addr.getOperand(1)))
00095       && (CN->getSExtValue() % 4 == 0 && CN->getSExtValue() >= 0)) {
00096       // Constant positive word offset from frame index
00097       Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), MVT::i32);
00098       Offset = CurDAG->getTargetConstant(CN->getSExtValue(), MVT::i32);
00099       return true;
00100     }
00101   }
00102   return false;
00103 }
00104 
00105 bool XCoreDAGToDAGISel::SelectADDRdpii(SDValue Op, SDValue Addr,
00106                                   SDValue &Base, SDValue &Offset) {
00107   if (Addr.getOpcode() == XCoreISD::DPRelativeWrapper) {
00108     Base = Addr.getOperand(0);
00109     Offset = CurDAG->getTargetConstant(0, MVT::i32);
00110     return true;
00111   }
00112   if (Addr.getOpcode() == ISD::ADD) {
00113     ConstantSDNode *CN = 0;
00114     if ((Addr.getOperand(0).getOpcode() == XCoreISD::DPRelativeWrapper)
00115       && (CN = dyn_cast<ConstantSDNode>(Addr.getOperand(1)))
00116       && (CN->getSExtValue() % 4 == 0)) {
00117       // Constant word offset from a object in the data region
00118       Base = Addr.getOperand(0).getOperand(0);
00119       Offset = CurDAG->getTargetConstant(CN->getSExtValue(), MVT::i32);
00120       return true;
00121     }
00122   }
00123   return false;
00124 }
00125 
00126 bool XCoreDAGToDAGISel::SelectADDRcpii(SDValue Op, SDValue Addr,
00127                                   SDValue &Base, SDValue &Offset) {
00128   if (Addr.getOpcode() == XCoreISD::CPRelativeWrapper) {
00129     Base = Addr.getOperand(0);
00130     Offset = CurDAG->getTargetConstant(0, MVT::i32);
00131     return true;
00132   }
00133   if (Addr.getOpcode() == ISD::ADD) {
00134     ConstantSDNode *CN = 0;
00135     if ((Addr.getOperand(0).getOpcode() == XCoreISD::CPRelativeWrapper)
00136       && (CN = dyn_cast<ConstantSDNode>(Addr.getOperand(1)))
00137       && (CN->getSExtValue() % 4 == 0)) {
00138       // Constant word offset from a object in the data region
00139       Base = Addr.getOperand(0).getOperand(0);
00140       Offset = CurDAG->getTargetConstant(CN->getSExtValue(), MVT::i32);
00141       return true;
00142     }
00143   }
00144   return false;
00145 }
00146 
00147 /// InstructionSelect - This callback is invoked by
00148 /// SelectionDAGISel when it has created a SelectionDAG for us to codegen.
00149 void XCoreDAGToDAGISel::
00150 InstructionSelect() {
00151   DEBUG(BB->dump());
00152 
00153   // Select target instructions for the DAG.
00154   SelectRoot(*CurDAG);
00155   
00156   CurDAG->RemoveDeadNodes();
00157 }
00158 
00159 SDNode *XCoreDAGToDAGISel::Select(SDValue Op) {
00160   SDNode *N = Op.getNode();
00161   MVT NVT = N->getValueType(0);
00162   if (NVT == MVT::i32) {
00163     switch (N->getOpcode()) {
00164       default: break;
00165       case ISD::Constant: {
00166         if (Predicate_immMskBitp(N)) {
00167           SDValue MskSize = Transform_msksize_xform(N);
00168           return CurDAG->getTargetNode(XCore::MKMSK_rus, MVT::i32, MskSize);
00169         }
00170         else if (! Predicate_immU16(N)) {
00171           unsigned Val = cast<ConstantSDNode>(N)->getZExtValue();
00172           SDValue CPIdx =
00173             CurDAG->getTargetConstantPool(ConstantInt::get(Type::Int32Ty, Val),
00174                                           TLI.getPointerTy());
00175           return CurDAG->getTargetNode(XCore::LDWCP_lru6, MVT::i32, MVT::Other,
00176                                             CPIdx, CurDAG->getEntryNode());
00177         }
00178         break;
00179       }
00180       case ISD::SMUL_LOHI: {
00181         // FIXME fold addition into the macc instruction
00182         if (!Subtarget.isXS1A()) {
00183           SDValue Zero(CurDAG->getTargetNode(XCore::LDC_ru6, MVT::i32,
00184                                   CurDAG->getTargetConstant(0, MVT::i32)), 0);
00185           SDValue Ops[] = { Zero, Zero, Op.getOperand(0), Op.getOperand(1) };
00186           SDNode *ResNode = CurDAG->getTargetNode(XCore::MACCS_l4r, MVT::i32,
00187                                                   MVT::i32, Ops, 4);
00188           ReplaceUses(SDValue(N, 0), SDValue(ResNode, 1));
00189           ReplaceUses(SDValue(N, 1), SDValue(ResNode, 0));
00190           return NULL;
00191         }
00192         break;
00193       }
00194       case ISD::UMUL_LOHI: {
00195         // FIXME fold addition into the macc / lmul instruction
00196         SDValue Zero(CurDAG->getTargetNode(XCore::LDC_ru6, MVT::i32,
00197                                   CurDAG->getTargetConstant(0, MVT::i32)), 0);
00198         SDValue Ops[] = { Op.getOperand(0), Op.getOperand(1),
00199                             Zero, Zero };
00200         SDNode *ResNode = CurDAG->getTargetNode(XCore::LMUL_l6r, MVT::i32,
00201                                                 MVT::i32, Ops, 4);
00202         ReplaceUses(SDValue(N, 0), SDValue(ResNode, 1));
00203         ReplaceUses(SDValue(N, 1), SDValue(ResNode, 0));
00204         return NULL;
00205       }
00206       case XCoreISD::LADD: {
00207         if (!Subtarget.isXS1A()) {
00208           SDValue Ops[] = { Op.getOperand(0), Op.getOperand(1),
00209                               Op.getOperand(2) };
00210           return CurDAG->getTargetNode(XCore::LADD_l5r, MVT::i32, MVT::i32,
00211                                        Ops, 3);
00212         }
00213         break;
00214       }
00215       case XCoreISD::LSUB: {
00216         if (!Subtarget.isXS1A()) {
00217           SDValue Ops[] = { Op.getOperand(0), Op.getOperand(1),
00218                               Op.getOperand(2) };
00219           return CurDAG->getTargetNode(XCore::LSUB_l5r, MVT::i32, MVT::i32,
00220                                        Ops, 3);
00221         }
00222         break;
00223       }
00224       // Other cases are autogenerated.
00225     }
00226   }
00227   return SelectCode(Op);
00228 }