XCoreISelDAGToDAG.cpp revision 234353
151078Speter//===-- XCoreISelDAGToDAG.cpp - A dag to dag inst selector for XCore ------===// 251078Speter// 351078Speter// The LLVM Compiler Infrastructure 451078Speter// 551078Speter// This file is distributed under the University of Illinois Open Source 651078Speter// License. See LICENSE.TXT for details. 751078Speter// 851078Speter//===----------------------------------------------------------------------===// 951078Speter// 1051078Speter// This file defines an instruction selector for the XCore target. 1151078Speter// 1251078Speter//===----------------------------------------------------------------------===// 1351078Speter 1451078Speter#include "XCore.h" 1551078Speter#include "XCoreTargetMachine.h" 1651078Speter#include "llvm/DerivedTypes.h" 1751078Speter#include "llvm/Function.h" 1851078Speter#include "llvm/Intrinsics.h" 1951078Speter#include "llvm/CallingConv.h" 2051078Speter#include "llvm/Constants.h" 2151078Speter#include "llvm/LLVMContext.h" 2251078Speter#include "llvm/CodeGen/MachineFrameInfo.h" 2351078Speter#include "llvm/CodeGen/MachineFunction.h" 2451078Speter#include "llvm/CodeGen/MachineInstrBuilder.h" 2551078Speter#include "llvm/CodeGen/MachineRegisterInfo.h" 2651078Speter#include "llvm/CodeGen/SelectionDAG.h" 2751078Speter#include "llvm/CodeGen/SelectionDAGISel.h" 2851078Speter#include "llvm/Target/TargetLowering.h" 2951078Speter#include "llvm/Support/Compiler.h" 3051078Speter#include "llvm/Support/Debug.h" 3151078Speter#include "llvm/Support/ErrorHandling.h" 3251078Speter#include "llvm/Support/raw_ostream.h" 33119419Sobrienusing namespace llvm; 34119419Sobrien 35119419Sobrien/// XCoreDAGToDAGISel - XCore specific code to select XCore machine 3651078Speter/// instructions for SelectionDAG operations. 3751078Speter/// 38131939Smarcelnamespace { 39131939Smarcel class XCoreDAGToDAGISel : public SelectionDAGISel { 4051078Speter const XCoreTargetLowering &Lowering; 4151078Speter const XCoreSubtarget &Subtarget; 4251078Speter 4351078Speter public: 4451078Speter XCoreDAGToDAGISel(XCoreTargetMachine &TM, CodeGenOpt::Level OptLevel) 4551078Speter : SelectionDAGISel(TM, OptLevel), 4651078Speter Lowering(*TM.getTargetLowering()), 4751078Speter Subtarget(*TM.getSubtargetImpl()) { } 4851078Speter 4951078Speter SDNode *Select(SDNode *N); 5051078Speter SDNode *SelectBRIND(SDNode *N); 5151078Speter 5276166Smarkm /// getI32Imm - Return a target constant with the specified value, of type 5365822Sjhb /// i32. 5451078Speter inline SDValue getI32Imm(unsigned Imm) { 5551078Speter return CurDAG->getTargetConstant(Imm, MVT::i32); 5651078Speter } 57131939Smarcel 5851078Speter inline bool immMskBitp(SDNode *inN) const { 59114216Skan ConstantSDNode *N = cast<ConstantSDNode>(inN); 6076166Smarkm uint32_t value = (uint32_t)N->getZExtValue(); 6176166Smarkm if (!isMask_32(value)) { 6276166Smarkm return false; 6376166Smarkm } 6476166Smarkm int msksize = 32 - CountLeadingZeros_32(value); 6576166Smarkm return (msksize >= 1 && msksize <= 8) || 66131094Sphk msksize == 16 || msksize == 24 || msksize == 32; 6776166Smarkm } 6851078Speter 6976166Smarkm // Complex Pattern Selectors. 7060471Snyan bool SelectADDRspii(SDValue Addr, SDValue &Base, SDValue &Offset); 7151078Speter bool SelectADDRdpii(SDValue Addr, SDValue &Base, SDValue &Offset); 7251078Speter bool SelectADDRcpii(SDValue Addr, SDValue &Base, SDValue &Offset); 7351078Speter 7493466Sbde virtual const char *getPassName() const { 75119485Snjl return "XCore DAG->DAG Pattern Instruction Selection"; 7651078Speter } 7786909Simp 7886909Simp // Include the pieces autogenerated from the target description. 7951078Speter #include "XCoreGenDAGISel.inc" 8051078Speter }; 8185302Simp} // end anonymous namespace 8285365Simp 8351078Speter/// createXCoreISelDag - This pass converts a legalized DAG into a 8451078Speter/// XCore-specific DAG, ready for instruction scheduling. 8577726Sjoerg/// 8651078SpeterFunctionPass *llvm::createXCoreISelDag(XCoreTargetMachine &TM, 8777726Sjoerg CodeGenOpt::Level OptLevel) { 8851078Speter return new XCoreDAGToDAGISel(TM, OptLevel); 8951078Speter} 9051078Speter 9151078Speterbool XCoreDAGToDAGISel::SelectADDRspii(SDValue Addr, SDValue &Base, 9251078Speter SDValue &Offset) { 9351078Speter FrameIndexSDNode *FIN = 0; 9451078Speter if ((FIN = dyn_cast<FrameIndexSDNode>(Addr))) { 9551078Speter Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), MVT::i32); 9693470Sbde Offset = CurDAG->getTargetConstant(0, MVT::i32); 9793470Sbde return true; 9893470Sbde } 9993470Sbde if (Addr.getOpcode() == ISD::ADD) { 10051078Speter ConstantSDNode *CN = 0; 10151078Speter if ((FIN = dyn_cast<FrameIndexSDNode>(Addr.getOperand(0))) 10251078Speter && (CN = dyn_cast<ConstantSDNode>(Addr.getOperand(1))) 10351078Speter && (CN->getSExtValue() % 4 == 0 && CN->getSExtValue() >= 0)) { 10451078Speter // Constant positive word offset from frame index 10551078Speter Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), MVT::i32); 10651078Speter Offset = CurDAG->getTargetConstant(CN->getSExtValue(), MVT::i32); 10751078Speter return true; 108104067Sphk } 109104067Sphk } 11051078Speter return false; 11151078Speter} 112120175Sbde 11351078Speterbool XCoreDAGToDAGISel::SelectADDRdpii(SDValue Addr, SDValue &Base, 114120175Sbde SDValue &Offset) { 115120175Sbde if (Addr.getOpcode() == XCoreISD::DPRelativeWrapper) { 11651078Speter Base = Addr.getOperand(0); 117120175Sbde Offset = CurDAG->getTargetConstant(0, MVT::i32); 11851078Speter return true; 11951078Speter } 120120175Sbde if (Addr.getOpcode() == ISD::ADD) { 121120175Sbde ConstantSDNode *CN = 0; 122120175Sbde if ((Addr.getOperand(0).getOpcode() == XCoreISD::DPRelativeWrapper) 123111613Sphk && (CN = dyn_cast<ConstantSDNode>(Addr.getOperand(1))) 124120175Sbde && (CN->getSExtValue() % 4 == 0 && CN->getSExtValue() >= 0)) { 125112384Ssobomax // Constant word offset from a object in the data region 12651078Speter Base = Addr.getOperand(0).getOperand(0); 12760471Snyan Offset = CurDAG->getTargetConstant(CN->getSExtValue(), MVT::i32); 12860471Snyan return true; 12960471Snyan } 13060471Snyan } 13160471Snyan return false; 13251078Speter} 13351078Speter 13451078Speterbool XCoreDAGToDAGISel::SelectADDRcpii(SDValue Addr, SDValue &Base, 13551078Speter SDValue &Offset) { 13651078Speter if (Addr.getOpcode() == XCoreISD::CPRelativeWrapper) { 13751078Speter Base = Addr.getOperand(0); 13851078Speter Offset = CurDAG->getTargetConstant(0, MVT::i32); 13951078Speter return true; 14053344Speter } 14151078Speter if (Addr.getOpcode() == ISD::ADD) { 14251078Speter ConstantSDNode *CN = 0; 14351078Speter if ((Addr.getOperand(0).getOpcode() == XCoreISD::CPRelativeWrapper) 14451078Speter && (CN = dyn_cast<ConstantSDNode>(Addr.getOperand(1))) 14551078Speter && (CN->getSExtValue() % 4 == 0 && CN->getSExtValue() >= 0)) { 14651078Speter // Constant word offset from a object in the data region 14751078Speter Base = Addr.getOperand(0).getOperand(0); 14851078Speter Offset = CurDAG->getTargetConstant(CN->getSExtValue(), MVT::i32); 14951078Speter return true; 15051078Speter } 15151078Speter } 15251078Speter return false; 15351078Speter} 15451078Speter 15551078SpeterSDNode *XCoreDAGToDAGISel::Select(SDNode *N) { 15651078Speter DebugLoc dl = N->getDebugLoc(); 15751078Speter switch (N->getOpcode()) { 15851078Speter default: break; 15951078Speter case ISD::Constant: { 16051078Speter uint64_t Val = cast<ConstantSDNode>(N)->getZExtValue(); 16151078Speter if (immMskBitp(N)) { 16251078Speter // Transformation function: get the size of a mask 16351078Speter // Look for the first non-zero bit 16451078Speter SDValue MskSize = getI32Imm(32 - CountLeadingZeros_32(Val)); 16551078Speter return CurDAG->getMachineNode(XCore::MKMSK_rus, dl, 16686909Simp MVT::i32, MskSize); 16751078Speter } 16851078Speter else if (!isUInt<16>(Val)) { 16986909Simp SDValue CPIdx = 17086909Simp CurDAG->getTargetConstantPool(ConstantInt::get( 17186909Simp Type::getInt32Ty(*CurDAG->getContext()), Val), 17286909Simp TLI.getPointerTy()); 17386909Simp SDNode *node = CurDAG->getMachineNode(XCore::LDWCP_lru6, dl, MVT::i32, 17486909Simp MVT::Other, CPIdx, 17586909Simp CurDAG->getEntryNode()); 17686909Simp MachineSDNode::mmo_iterator MemOp = MF->allocateMemRefsArray(1); 17786909Simp MemOp[0] = MF->getMachineMemOperand( 17886909Simp MachinePointerInfo::getConstantPool(), MachineMemOperand::MOLoad, 4, 4); 17986909Simp cast<MachineSDNode>(node)->setMemRefs(MemOp, MemOp + 1); 18086909Simp return node; 18186909Simp } 18286909Simp break; 18386909Simp } 18486909Simp case XCoreISD::LADD: { 18586909Simp SDValue Ops[] = { N->getOperand(0), N->getOperand(1), 18651078Speter N->getOperand(2) }; 18786909Simp return CurDAG->getMachineNode(XCore::LADD_l5r, dl, MVT::i32, MVT::i32, 18886909Simp Ops, 3); 18986909Simp } 19086909Simp case XCoreISD::LSUB: { 19186909Simp SDValue Ops[] = { N->getOperand(0), N->getOperand(1), 19286909Simp N->getOperand(2) }; 19386909Simp return CurDAG->getMachineNode(XCore::LSUB_l5r, dl, MVT::i32, MVT::i32, 19486909Simp Ops, 3); 19586909Simp } 19686909Simp case XCoreISD::MACCU: { 19786909Simp SDValue Ops[] = { N->getOperand(0), N->getOperand(1), 19886909Simp N->getOperand(2), N->getOperand(3) }; 19986909Simp return CurDAG->getMachineNode(XCore::MACCU_l4r, dl, MVT::i32, MVT::i32, 20086909Simp Ops, 4); 201120175Sbde } 20286909Simp case XCoreISD::MACCS: { 203120189Sbde SDValue Ops[] = { N->getOperand(0), N->getOperand(1), 20486909Simp N->getOperand(2), N->getOperand(3) }; 20586909Simp return CurDAG->getMachineNode(XCore::MACCS_l4r, dl, MVT::i32, MVT::i32, 20686909Simp Ops, 4); 20786909Simp } 20886909Simp case XCoreISD::LMUL: { 20986909Simp SDValue Ops[] = { N->getOperand(0), N->getOperand(1), 21086909Simp N->getOperand(2), N->getOperand(3) }; 21186909Simp return CurDAG->getMachineNode(XCore::LMUL_l6r, dl, MVT::i32, MVT::i32, 21286909Simp Ops, 4); 21386909Simp } 21486909Simp case ISD::INTRINSIC_WO_CHAIN: { 21586909Simp unsigned IntNo = cast<ConstantSDNode>(N->getOperand(0))->getZExtValue(); 21686909Simp switch (IntNo) { 21786909Simp case Intrinsic::xcore_crc8: 21886909Simp SDValue Ops[] = { N->getOperand(1), N->getOperand(2), N->getOperand(3) }; 21986909Simp return CurDAG->getMachineNode(XCore::CRC8_l4r, dl, MVT::i32, MVT::i32, 22086909Simp Ops, 3); 22186909Simp } 22286909Simp break; 22386909Simp } 22486909Simp case ISD::BRIND: 22586909Simp if (SDNode *ResNode = SelectBRIND(N)) 22686909Simp return ResNode; 22786909Simp break; 22886909Simp // Other cases are autogenerated. 22986909Simp } 23086909Simp return SelectCode(N); 23186909Simp} 23286909Simp 23386909Simp/// Given a chain return a new chain where any appearance of Old is replaced 234120189Sbde/// by New. There must be at most one instruction between Old and Chain and 23586909Simp/// this instruction must be a TokenFactor. Returns an empty SDValue if 23686909Simp/// these conditions don't hold. 23786909Simpstatic SDValue 23886909SimpreplaceInChain(SelectionDAG *CurDAG, SDValue Chain, SDValue Old, SDValue New) 23986909Simp{ 24086909Simp if (Chain == Old) 24186909Simp return New; 24286909Simp if (Chain->getOpcode() != ISD::TokenFactor) 24386909Simp return SDValue(); 24486909Simp SmallVector<SDValue, 8> Ops; 245111613Sphk bool found = false; 246119485Snjl for (unsigned i = 0, e = Chain->getNumOperands(); i != e; ++i) { 247119485Snjl if (Chain->getOperand(i) == Old) { 248119485Snjl Ops.push_back(New); 24986909Simp found = true; 25086909Simp } else { 25186909Simp Ops.push_back(Chain->getOperand(i)); 25286909Simp } 25386909Simp } 25486909Simp if (!found) 25589986Sjhay return SDValue(); 25689986Sjhay return CurDAG->getNode(ISD::TokenFactor, Chain->getDebugLoc(), MVT::Other, 25786909Simp &Ops[0], Ops.size()); 25886909Simp} 259116120Sscottl 260116120SscottlSDNode *XCoreDAGToDAGISel::SelectBRIND(SDNode *N) { 261130585Sphk DebugLoc dl = N->getDebugLoc(); 26286909Simp // (brind (int_xcore_checkevent (addr))) 26386909Simp SDValue Chain = N->getOperand(0); 26486909Simp SDValue Addr = N->getOperand(1); 26586909Simp if (Addr->getOpcode() != ISD::INTRINSIC_W_CHAIN) 26686909Simp return 0; 26786909Simp unsigned IntNo = cast<ConstantSDNode>(Addr->getOperand(1))->getZExtValue(); 26886909Simp if (IntNo != Intrinsic::xcore_checkevent) 26986909Simp return 0; 27086909Simp SDValue nextAddr = Addr->getOperand(2); 27186909Simp SDValue CheckEventChainOut(Addr.getNode(), 1); 27293010Sbde if (!CheckEventChainOut.use_empty()) { 27351078Speter // If the chain out of the checkevent intrinsic is an operand of the 27451078Speter // indirect branch or used in a TokenFactor which is the operand of the 275131373Sphk // indirect branch then build a new chain which uses the chain coming into 27651078Speter // the checkevent intrinsic instead. 27793010Sbde SDValue CheckEventChainIn = Addr->getOperand(0); 27893010Sbde SDValue NewChain = replaceInChain(CurDAG, Chain, CheckEventChainOut, 27993010Sbde CheckEventChainIn); 28093010Sbde if (!NewChain.getNode()) 28193010Sbde return 0; 282131094Sphk Chain = NewChain; 28393010Sbde } 28493010Sbde // Enable events on the thread using setsr 1 and then disable them immediately 28593010Sbde // after with clrsr 1. If any resources owned by the thread are ready an event 28693010Sbde // will be taken. If no resource is ready we branch to the address which was 28793010Sbde // the operand to the checkevent intrinsic. 28893010Sbde SDValue constOne = getI32Imm(1); 28951078Speter SDValue Glue = 29051078Speter SDValue(CurDAG->getMachineNode(XCore::SETSR_branch_u6, dl, MVT::Glue, 29185365Simp constOne, Chain), 0); 29270174Sjhb Glue = 29370174Sjhb SDValue(CurDAG->getMachineNode(XCore::CLRSR_branch_u6, dl, MVT::Glue, 29451078Speter constOne, Glue), 0); 29551078Speter if (nextAddr->getOpcode() == XCoreISD::PCRelativeWrapper && 29685365Simp nextAddr->getOperand(0)->getOpcode() == ISD::TargetBlockAddress) { 29751078Speter return CurDAG->SelectNodeTo(N, XCore::BRFU_lu6, MVT::Other, 29886909Simp nextAddr->getOperand(0), Glue); 29951078Speter } 30051078Speter return CurDAG->SelectNodeTo(N, XCore::BAU_1r, MVT::Other, nextAddr, Glue); 30151078Speter} 30251078Speter