XCoreISelDAGToDAG.cpp revision 193323
150397Sobrien//===-- XCoreISelDAGToDAG.cpp - A dag to dag inst selector for XCore ------===// 2169689Skan// 3132718Skan// The LLVM Compiler Infrastructure 450397Sobrien// 550397Sobrien// This file is distributed under the University of Illinois Open Source 6132718Skan// License. See LICENSE.TXT for details. 750397Sobrien// 8132718Skan//===----------------------------------------------------------------------===// 950397Sobrien// 1050397Sobrien// This file defines an instruction selector for the XCore target. 1150397Sobrien// 1250397Sobrien//===----------------------------------------------------------------------===// 13132718Skan 1450397Sobrien#include "XCore.h" 1550397Sobrien#include "XCoreISelLowering.h" 1650397Sobrien#include "XCoreTargetMachine.h" 1750397Sobrien#include "llvm/DerivedTypes.h" 1850397Sobrien#include "llvm/Function.h" 19132718Skan#include "llvm/Intrinsics.h" 20169689Skan#include "llvm/CallingConv.h" 21169689Skan#include "llvm/Constants.h" 2250397Sobrien#include "llvm/CodeGen/MachineFrameInfo.h" 23132718Skan#include "llvm/CodeGen/MachineFunction.h" 24132718Skan#include "llvm/CodeGen/MachineInstrBuilder.h" 25132718Skan#include "llvm/CodeGen/MachineRegisterInfo.h" 26169689Skan#include "llvm/CodeGen/SelectionDAG.h" 27169689Skan#include "llvm/CodeGen/SelectionDAGISel.h" 28169689Skan#include "llvm/Target/TargetLowering.h" 29169689Skan#include "llvm/Support/Compiler.h" 30169689Skan#include "llvm/Support/Debug.h" 31169689Skan#include <queue> 32169689Skan#include <set> 33169689Skanusing namespace llvm; 34132718Skan 35132718Skan/// XCoreDAGToDAGISel - XCore specific code to select XCore machine 3650397Sobrien/// instructions for SelectionDAG operations. 3790075Sobrien/// 3850397Sobriennamespace { 3950397Sobrien class XCoreDAGToDAGISel : public SelectionDAGISel { 4050397Sobrien XCoreTargetLowering &Lowering; 4150397Sobrien const XCoreSubtarget &Subtarget; 4250397Sobrien 4350397Sobrien public: 4450397Sobrien XCoreDAGToDAGISel(XCoreTargetMachine &TM) 4550397Sobrien : SelectionDAGISel(TM), 4690075Sobrien Lowering(*TM.getTargetLowering()), 4750397Sobrien Subtarget(*TM.getSubtargetImpl()) { } 4850397Sobrien 49169689Skan SDNode *Select(SDValue Op); 5050397Sobrien 51132718Skan /// getI32Imm - Return a target constant with the specified value, of type 52132718Skan /// i32. 5390075Sobrien inline SDValue getI32Imm(unsigned Imm) { 5490075Sobrien return CurDAG->getTargetConstant(Imm, MVT::i32); 55132718Skan } 56132718Skan 5790075Sobrien // Complex Pattern Selectors. 5850397Sobrien bool SelectADDRspii(SDValue Op, SDValue Addr, SDValue &Base, 5950397Sobrien SDValue &Offset); 6050397Sobrien bool SelectADDRdpii(SDValue Op, SDValue Addr, SDValue &Base, 6150397Sobrien SDValue &Offset); 6250397Sobrien bool SelectADDRcpii(SDValue Op, SDValue Addr, SDValue &Base, 6350397Sobrien SDValue &Offset); 6450397Sobrien 6550397Sobrien virtual void InstructionSelect(); 6650397Sobrien 6796263Sobrien virtual const char *getPassName() const { 68132718Skan return "XCore DAG->DAG Pattern Instruction Selection"; 6950397Sobrien } 7090075Sobrien 7150397Sobrien // Include the pieces autogenerated from the target description. 7250397Sobrien #include "XCoreGenDAGISel.inc" 7350397Sobrien }; 7450397Sobrien} // end anonymous namespace 7550397Sobrien 7650397Sobrien/// createXCoreISelDag - This pass converts a legalized DAG into a 7750397Sobrien/// XCore-specific DAG, ready for instruction scheduling. 7850397Sobrien/// 7990075SobrienFunctionPass *llvm::createXCoreISelDag(XCoreTargetMachine &TM) { 8090075Sobrien return new XCoreDAGToDAGISel(TM); 8190075Sobrien} 8290075Sobrien 8350397Sobrienbool XCoreDAGToDAGISel::SelectADDRspii(SDValue Op, SDValue Addr, 8450397Sobrien SDValue &Base, SDValue &Offset) { 8550397Sobrien FrameIndexSDNode *FIN = 0; 8650397Sobrien if ((FIN = dyn_cast<FrameIndexSDNode>(Addr))) { 8750397Sobrien Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), MVT::i32); 8850397Sobrien Offset = CurDAG->getTargetConstant(0, MVT::i32); 8950397Sobrien return true; 9050397Sobrien } 9150397Sobrien if (Addr.getOpcode() == ISD::ADD) { 9250397Sobrien ConstantSDNode *CN = 0; 9390075Sobrien if ((FIN = dyn_cast<FrameIndexSDNode>(Addr.getOperand(0))) 9450397Sobrien && (CN = dyn_cast<ConstantSDNode>(Addr.getOperand(1))) 9550397Sobrien && (CN->getSExtValue() % 4 == 0 && CN->getSExtValue() >= 0)) { 9690075Sobrien // Constant positive word offset from frame index 9790075Sobrien Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), MVT::i32); 9850397Sobrien Offset = CurDAG->getTargetConstant(CN->getSExtValue(), MVT::i32); 9950397Sobrien return true; 100169689Skan } 10150397Sobrien } 10250397Sobrien return false; 10350397Sobrien} 104117395Skan 105117395Skanbool XCoreDAGToDAGISel::SelectADDRdpii(SDValue Op, SDValue Addr, 106117395Skan SDValue &Base, SDValue &Offset) { 10750397Sobrien if (Addr.getOpcode() == XCoreISD::DPRelativeWrapper) { 10850397Sobrien Base = Addr.getOperand(0); 10950397Sobrien Offset = CurDAG->getTargetConstant(0, MVT::i32); 11050397Sobrien return true; 11150397Sobrien } 11250397Sobrien if (Addr.getOpcode() == ISD::ADD) { 11350397Sobrien ConstantSDNode *CN = 0; 11450397Sobrien if ((Addr.getOperand(0).getOpcode() == XCoreISD::DPRelativeWrapper) 11550397Sobrien && (CN = dyn_cast<ConstantSDNode>(Addr.getOperand(1))) 11650397Sobrien && (CN->getSExtValue() % 4 == 0)) { 11750397Sobrien // Constant word offset from a object in the data region 11850397Sobrien Base = Addr.getOperand(0).getOperand(0); 11950397Sobrien Offset = CurDAG->getTargetConstant(CN->getSExtValue(), MVT::i32); 12050397Sobrien return true; 12150397Sobrien } 12290075Sobrien } 12350397Sobrien return false; 124169689Skan} 125169689Skan 126169689Skanbool XCoreDAGToDAGISel::SelectADDRcpii(SDValue Op, SDValue Addr, 127169689Skan SDValue &Base, SDValue &Offset) { 128169689Skan if (Addr.getOpcode() == XCoreISD::CPRelativeWrapper) { 129169689Skan Base = Addr.getOperand(0); 130169689Skan Offset = CurDAG->getTargetConstant(0, MVT::i32); 131169689Skan return true; 132169689Skan } 133169689Skan if (Addr.getOpcode() == ISD::ADD) { 134169689Skan ConstantSDNode *CN = 0; 13550397Sobrien if ((Addr.getOperand(0).getOpcode() == XCoreISD::CPRelativeWrapper) 13650397Sobrien && (CN = dyn_cast<ConstantSDNode>(Addr.getOperand(1))) 13790075Sobrien && (CN->getSExtValue() % 4 == 0)) { 13850397Sobrien // Constant word offset from a object in the data region 13950397Sobrien Base = Addr.getOperand(0).getOperand(0); 14050397Sobrien Offset = CurDAG->getTargetConstant(CN->getSExtValue(), MVT::i32); 14150397Sobrien return true; 142169689Skan } 14350397Sobrien } 14450397Sobrien return false; 14550397Sobrien} 14690075Sobrien 14750397Sobrien/// InstructionSelect - This callback is invoked by 14850397Sobrien/// SelectionDAGISel when it has created a SelectionDAG for us to codegen. 149132718Skanvoid XCoreDAGToDAGISel:: 150132718SkanInstructionSelect() { 15150397Sobrien DEBUG(BB->dump()); 15250397Sobrien 15350397Sobrien // Select target instructions for the DAG. 15450397Sobrien SelectRoot(*CurDAG); 15550397Sobrien 15650397Sobrien CurDAG->RemoveDeadNodes(); 15750397Sobrien} 15850397Sobrien 15950397SobrienSDNode *XCoreDAGToDAGISel::Select(SDValue Op) { 16050397Sobrien SDNode *N = Op.getNode(); 16150397Sobrien DebugLoc dl = N->getDebugLoc(); 16250397Sobrien MVT NVT = N->getValueType(0); 16350397Sobrien if (NVT == MVT::i32) { 16450397Sobrien switch (N->getOpcode()) { 16550397Sobrien default: break; 16690075Sobrien case ISD::Constant: { 16750397Sobrien if (Predicate_immMskBitp(N)) { 16896263Sobrien SDValue MskSize = Transform_msksize_xform(N); 16996263Sobrien return CurDAG->getTargetNode(XCore::MKMSK_rus, dl, MVT::i32, MskSize); 17096263Sobrien } 17150397Sobrien else if (! Predicate_immU16(N)) { 17250397Sobrien unsigned Val = cast<ConstantSDNode>(N)->getZExtValue(); 17350397Sobrien SDValue CPIdx = 17450397Sobrien CurDAG->getTargetConstantPool(ConstantInt::get(Type::Int32Ty, Val), 17550397Sobrien TLI.getPointerTy()); 17650397Sobrien return CurDAG->getTargetNode(XCore::LDWCP_lru6, dl, MVT::i32, 17750397Sobrien MVT::Other, CPIdx, 17890075Sobrien CurDAG->getEntryNode()); 17950397Sobrien } 18050397Sobrien break; 181117395Skan } 182117395Skan case ISD::SMUL_LOHI: { 18390075Sobrien // FIXME fold addition into the macc instruction 18490075Sobrien if (!Subtarget.isXS1A()) { 18590075Sobrien SDValue Zero(CurDAG->getTargetNode(XCore::LDC_ru6, dl, MVT::i32, 18690075Sobrien CurDAG->getTargetConstant(0, MVT::i32)), 0); 18790075Sobrien SDValue Ops[] = { Zero, Zero, Op.getOperand(0), Op.getOperand(1) }; 18890075Sobrien SDNode *ResNode = CurDAG->getTargetNode(XCore::MACCS_l4r, dl, 18990075Sobrien MVT::i32, MVT::i32, Ops, 4); 19090075Sobrien ReplaceUses(SDValue(N, 0), SDValue(ResNode, 1)); 19150397Sobrien ReplaceUses(SDValue(N, 1), SDValue(ResNode, 0)); 19290075Sobrien return NULL; 193132718Skan } 194132718Skan break; 195132718Skan } 196169689Skan case ISD::UMUL_LOHI: { 19790075Sobrien // FIXME fold addition into the macc / lmul instruction 19890075Sobrien SDValue Zero(CurDAG->getTargetNode(XCore::LDC_ru6, dl, MVT::i32, 19950397Sobrien CurDAG->getTargetConstant(0, MVT::i32)), 0); 200132718Skan SDValue Ops[] = { Op.getOperand(0), Op.getOperand(1), 201132718Skan Zero, Zero }; 202132718Skan SDNode *ResNode = CurDAG->getTargetNode(XCore::LMUL_l6r, dl, MVT::i32, 203132718Skan MVT::i32, Ops, 4); 204132718Skan ReplaceUses(SDValue(N, 0), SDValue(ResNode, 1)); 205132718Skan ReplaceUses(SDValue(N, 1), SDValue(ResNode, 0)); 206132718Skan return NULL; 20796263Sobrien } 20896263Sobrien case XCoreISD::LADD: { 20996263Sobrien if (!Subtarget.isXS1A()) { 21096263Sobrien SDValue Ops[] = { Op.getOperand(0), Op.getOperand(1), 21196263Sobrien Op.getOperand(2) }; 21296263Sobrien return CurDAG->getTargetNode(XCore::LADD_l5r, dl, MVT::i32, MVT::i32, 21396263Sobrien Ops, 3); 214169689Skan } 215132718Skan break; 216169689Skan } 217132718Skan case XCoreISD::LSUB: { 218169689Skan if (!Subtarget.isXS1A()) { 219132718Skan SDValue Ops[] = { Op.getOperand(0), Op.getOperand(1), 220122180Skan Op.getOperand(2) }; 221122180Skan return CurDAG->getTargetNode(XCore::LSUB_l5r, dl, MVT::i32, MVT::i32, 222122180Skan Ops, 3); 223122180Skan } 224169689Skan break; 225169689Skan } 226169689Skan // Other cases are autogenerated. 227169689Skan } 22896263Sobrien } 229169689Skan return SelectCode(Op); 230169689Skan} 231169689Skan