XCoreISelDAGToDAG.cpp revision 288943
1251875Speter//===-- XCoreISelDAGToDAG.cpp - A dag to dag inst selector for XCore ------===// 2251875Speter// 3251875Speter// The LLVM Compiler Infrastructure 4251875Speter// 5251875Speter// This file is distributed under the University of Illinois Open Source 6251875Speter// License. See LICENSE.TXT for details. 7251875Speter// 8251875Speter//===----------------------------------------------------------------------===// 9251875Speter// 10251875Speter// This file defines an instruction selector for the XCore target. 11251875Speter// 12251875Speter//===----------------------------------------------------------------------===// 13251875Speter 14251875Speter#include "XCore.h" 15251875Speter#include "XCoreTargetMachine.h" 16251875Speter#include "llvm/CodeGen/MachineFrameInfo.h" 17251875Speter#include "llvm/CodeGen/MachineFunction.h" 18251875Speter#include "llvm/CodeGen/MachineInstrBuilder.h" 19251875Speter#include "llvm/CodeGen/MachineRegisterInfo.h" 20251875Speter#include "llvm/CodeGen/SelectionDAG.h" 21251875Speter#include "llvm/CodeGen/SelectionDAGISel.h" 22251875Speter#include "llvm/IR/CallingConv.h" 23251875Speter#include "llvm/IR/Constants.h" 24251875Speter#include "llvm/IR/DerivedTypes.h" 25251875Speter#include "llvm/IR/Function.h" 26251875Speter#include "llvm/IR/Intrinsics.h" 27251875Speter#include "llvm/IR/LLVMContext.h" 28251875Speter#include "llvm/Support/Compiler.h" 29251875Speter#include "llvm/Support/Debug.h" 30251875Speter#include "llvm/Support/ErrorHandling.h" 31251875Speter#include "llvm/Support/raw_ostream.h" 32251875Speter#include "llvm/Target/TargetLowering.h" 33251875Speterusing namespace llvm; 34251875Speter 35251875Speter/// XCoreDAGToDAGISel - XCore specific code to select XCore machine 36251875Speter/// instructions for SelectionDAG operations. 37251875Speter/// 38251875Speternamespace { 39251875Speter class XCoreDAGToDAGISel : public SelectionDAGISel { 40251875Speter 41251875Speter public: 42251875Speter XCoreDAGToDAGISel(XCoreTargetMachine &TM, CodeGenOpt::Level OptLevel) 43251875Speter : SelectionDAGISel(TM, OptLevel) {} 44251875Speter 45251875Speter SDNode *Select(SDNode *N) override; 46251875Speter SDNode *SelectBRIND(SDNode *N); 47251875Speter 48251875Speter /// getI32Imm - Return a target constant with the specified value, of type 49251875Speter /// i32. 50251875Speter inline SDValue getI32Imm(unsigned Imm, SDLoc dl) { 51251875Speter return CurDAG->getTargetConstant(Imm, dl, MVT::i32); 52251875Speter } 53251875Speter 54251875Speter inline bool immMskBitp(SDNode *inN) const { 55251875Speter ConstantSDNode *N = cast<ConstantSDNode>(inN); 56251875Speter uint32_t value = (uint32_t)N->getZExtValue(); 57251875Speter if (!isMask_32(value)) { 58251875Speter return false; 59251875Speter } 60251875Speter int msksize = 32 - countLeadingZeros(value); 61251875Speter return (msksize >= 1 && msksize <= 8) || 62251875Speter msksize == 16 || msksize == 24 || msksize == 32; 63251875Speter } 64251875Speter 65251875Speter // Complex Pattern Selectors. 66251875Speter bool SelectADDRspii(SDValue Addr, SDValue &Base, SDValue &Offset); 67251875Speter 68251875Speter bool SelectInlineAsmMemoryOperand(const SDValue &Op, unsigned ConstraintID, 69251875Speter std::vector<SDValue> &OutOps) override; 70251875Speter 71251875Speter const char *getPassName() const override { 72251875Speter return "XCore DAG->DAG Pattern Instruction Selection"; 73251875Speter } 74251875Speter 75251875Speter // Include the pieces autogenerated from the target description. 76251875Speter #include "XCoreGenDAGISel.inc" 77251875Speter }; 78251875Speter} // end anonymous namespace 79251875Speter 80251875Speter/// createXCoreISelDag - This pass converts a legalized DAG into a 81251875Speter/// XCore-specific DAG, ready for instruction scheduling. 82251875Speter/// 83251875SpeterFunctionPass *llvm::createXCoreISelDag(XCoreTargetMachine &TM, 84251875Speter CodeGenOpt::Level OptLevel) { 85251875Speter return new XCoreDAGToDAGISel(TM, OptLevel); 86251875Speter} 87251875Speter 88251875Speterbool XCoreDAGToDAGISel::SelectADDRspii(SDValue Addr, SDValue &Base, 89251875Speter SDValue &Offset) { 90251875Speter FrameIndexSDNode *FIN = nullptr; 91251875Speter if ((FIN = dyn_cast<FrameIndexSDNode>(Addr))) { 92251875Speter Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), MVT::i32); 93251875Speter Offset = CurDAG->getTargetConstant(0, SDLoc(Addr), MVT::i32); 94251875Speter return true; 95251875Speter } 96251875Speter if (Addr.getOpcode() == ISD::ADD) { 97251875Speter ConstantSDNode *CN = nullptr; 98251875Speter if ((FIN = dyn_cast<FrameIndexSDNode>(Addr.getOperand(0))) 99251875Speter && (CN = dyn_cast<ConstantSDNode>(Addr.getOperand(1))) 100251875Speter && (CN->getSExtValue() % 4 == 0 && CN->getSExtValue() >= 0)) { 101251875Speter // Constant positive word offset from frame index 102251875Speter Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), MVT::i32); 103251875Speter Offset = CurDAG->getTargetConstant(CN->getSExtValue(), SDLoc(Addr), 104251875Speter MVT::i32); 105251875Speter return true; 106251875Speter } 107251875Speter } 108251875Speter return false; 109251875Speter} 110251875Speter 111251875Speterbool XCoreDAGToDAGISel:: 112251875SpeterSelectInlineAsmMemoryOperand(const SDValue &Op, unsigned ConstraintID, 113251875Speter std::vector<SDValue> &OutOps) { 114251875Speter SDValue Reg; 115251875Speter switch (ConstraintID) { 116251875Speter default: return true; 117251875Speter case InlineAsm::Constraint_m: // Memory. 118251875Speter switch (Op.getOpcode()) { 119251875Speter default: return true; 120251875Speter case XCoreISD::CPRelativeWrapper: 121251875Speter Reg = CurDAG->getRegister(XCore::CP, MVT::i32); 122251875Speter break; 123251875Speter case XCoreISD::DPRelativeWrapper: 124251875Speter Reg = CurDAG->getRegister(XCore::DP, MVT::i32); 125251875Speter break; 126251875Speter } 127251875Speter } 128251875Speter OutOps.push_back(Reg); 129251875Speter OutOps.push_back(Op.getOperand(0)); 130251875Speter return false; 131251875Speter} 132251875Speter 133251875SpeterSDNode *XCoreDAGToDAGISel::Select(SDNode *N) { 134251875Speter SDLoc dl(N); 135251875Speter switch (N->getOpcode()) { 136251875Speter default: break; 137251875Speter case ISD::Constant: { 138251875Speter uint64_t Val = cast<ConstantSDNode>(N)->getZExtValue(); 139251875Speter if (immMskBitp(N)) { 140251875Speter // Transformation function: get the size of a mask 141251875Speter // Look for the first non-zero bit 142251875Speter SDValue MskSize = getI32Imm(32 - countLeadingZeros((uint32_t)Val), dl); 143251875Speter return CurDAG->getMachineNode(XCore::MKMSK_rus, dl, 144269847Speter MVT::i32, MskSize); 145269847Speter } 146269847Speter else if (!isUInt<16>(Val)) { 147269847Speter SDValue CPIdx = CurDAG->getTargetConstantPool( 148269847Speter ConstantInt::get(Type::getInt32Ty(*CurDAG->getContext()), Val), 149269847Speter getTargetLowering()->getPointerTy(CurDAG->getDataLayout())); 150269847Speter SDNode *node = CurDAG->getMachineNode(XCore::LDWCP_lru6, dl, MVT::i32, 151269847Speter MVT::Other, CPIdx, 152269847Speter CurDAG->getEntryNode()); 153269847Speter MachineSDNode::mmo_iterator MemOp = MF->allocateMemRefsArray(1); 154269847Speter MemOp[0] = MF->getMachineMemOperand( 155269847Speter MachinePointerInfo::getConstantPool(), MachineMemOperand::MOLoad, 4, 4); 156251875Speter cast<MachineSDNode>(node)->setMemRefs(MemOp, MemOp + 1); 157251875Speter return node; 158251875Speter } 159251875Speter break; 160251875Speter } 161251875Speter case XCoreISD::LADD: { 162251875Speter SDValue Ops[] = { N->getOperand(0), N->getOperand(1), 163251875Speter N->getOperand(2) }; 164251875Speter return CurDAG->getMachineNode(XCore::LADD_l5r, dl, MVT::i32, MVT::i32, 165251875Speter Ops); 166251875Speter } 167251875Speter case XCoreISD::LSUB: { 168251875Speter SDValue Ops[] = { N->getOperand(0), N->getOperand(1), 169251875Speter N->getOperand(2) }; 170251875Speter return CurDAG->getMachineNode(XCore::LSUB_l5r, dl, MVT::i32, MVT::i32, 171251875Speter Ops); 172251875Speter } 173251875Speter case XCoreISD::MACCU: { 174251875Speter SDValue Ops[] = { N->getOperand(0), N->getOperand(1), 175251875Speter N->getOperand(2), N->getOperand(3) }; 176251875Speter return CurDAG->getMachineNode(XCore::MACCU_l4r, dl, MVT::i32, MVT::i32, 177251875Speter Ops); 178251875Speter } 179251875Speter case XCoreISD::MACCS: { 180251875Speter SDValue Ops[] = { N->getOperand(0), N->getOperand(1), 181251875Speter N->getOperand(2), N->getOperand(3) }; 182251875Speter return CurDAG->getMachineNode(XCore::MACCS_l4r, dl, MVT::i32, MVT::i32, 183251875Speter Ops); 184251875Speter } 185251875Speter case XCoreISD::LMUL: { 186251875Speter SDValue Ops[] = { N->getOperand(0), N->getOperand(1), 187251875Speter N->getOperand(2), N->getOperand(3) }; 188251875Speter return CurDAG->getMachineNode(XCore::LMUL_l6r, dl, MVT::i32, MVT::i32, 189251875Speter Ops); 190251875Speter } 191251875Speter case XCoreISD::CRC8: { 192251875Speter SDValue Ops[] = { N->getOperand(0), N->getOperand(1), N->getOperand(2) }; 193251875Speter return CurDAG->getMachineNode(XCore::CRC8_l4r, dl, MVT::i32, MVT::i32, 194251875Speter Ops); 195251875Speter } 196251875Speter case ISD::BRIND: 197251875Speter if (SDNode *ResNode = SelectBRIND(N)) 198251875Speter return ResNode; 199251875Speter break; 200251875Speter // Other cases are autogenerated. 201251875Speter } 202251875Speter return SelectCode(N); 203251875Speter} 204251875Speter 205251875Speter/// Given a chain return a new chain where any appearance of Old is replaced 206251875Speter/// by New. There must be at most one instruction between Old and Chain and 207251875Speter/// this instruction must be a TokenFactor. Returns an empty SDValue if 208251875Speter/// these conditions don't hold. 209251875Speterstatic SDValue 210251875SpeterreplaceInChain(SelectionDAG *CurDAG, SDValue Chain, SDValue Old, SDValue New) 211251875Speter{ 212251875Speter if (Chain == Old) 213251875Speter return New; 214251875Speter if (Chain->getOpcode() != ISD::TokenFactor) 215251875Speter return SDValue(); 216251875Speter SmallVector<SDValue, 8> Ops; 217251875Speter bool found = false; 218251875Speter for (unsigned i = 0, e = Chain->getNumOperands(); i != e; ++i) { 219251875Speter if (Chain->getOperand(i) == Old) { 220251875Speter Ops.push_back(New); 221251875Speter found = true; 222251875Speter } else { 223251875Speter Ops.push_back(Chain->getOperand(i)); 224251875Speter } 225251875Speter } 226251875Speter if (!found) 227251875Speter return SDValue(); 228251875Speter return CurDAG->getNode(ISD::TokenFactor, SDLoc(Chain), MVT::Other, Ops); 229251875Speter} 230251875Speter 231251875SpeterSDNode *XCoreDAGToDAGISel::SelectBRIND(SDNode *N) { 232251875Speter SDLoc dl(N); 233251875Speter // (brind (int_xcore_checkevent (addr))) 234251875Speter SDValue Chain = N->getOperand(0); 235251875Speter SDValue Addr = N->getOperand(1); 236251875Speter if (Addr->getOpcode() != ISD::INTRINSIC_W_CHAIN) 237251875Speter return nullptr; 238251875Speter unsigned IntNo = cast<ConstantSDNode>(Addr->getOperand(1))->getZExtValue(); 239251875Speter if (IntNo != Intrinsic::xcore_checkevent) 240251875Speter return nullptr; 241251875Speter SDValue nextAddr = Addr->getOperand(2); 242251875Speter SDValue CheckEventChainOut(Addr.getNode(), 1); 243251875Speter if (!CheckEventChainOut.use_empty()) { 244251875Speter // If the chain out of the checkevent intrinsic is an operand of the 245251875Speter // indirect branch or used in a TokenFactor which is the operand of the 246251875Speter // indirect branch then build a new chain which uses the chain coming into 247251875Speter // the checkevent intrinsic instead. 248251875Speter SDValue CheckEventChainIn = Addr->getOperand(0); 249251875Speter SDValue NewChain = replaceInChain(CurDAG, Chain, CheckEventChainOut, 250251875Speter CheckEventChainIn); 251251875Speter if (!NewChain.getNode()) 252251875Speter return nullptr; 253251875Speter Chain = NewChain; 254251875Speter } 255251875Speter // Enable events on the thread using setsr 1 and then disable them immediately 256251875Speter // after with clrsr 1. If any resources owned by the thread are ready an event 257251875Speter // will be taken. If no resource is ready we branch to the address which was 258251875Speter // the operand to the checkevent intrinsic. 259251875Speter SDValue constOne = getI32Imm(1, dl); 260251875Speter SDValue Glue = 261251875Speter SDValue(CurDAG->getMachineNode(XCore::SETSR_branch_u6, dl, MVT::Glue, 262251875Speter constOne, Chain), 0); 263251875Speter Glue = 264251875Speter SDValue(CurDAG->getMachineNode(XCore::CLRSR_branch_u6, dl, MVT::Glue, 265251875Speter constOne, Glue), 0); 266251875Speter if (nextAddr->getOpcode() == XCoreISD::PCRelativeWrapper && 267251875Speter nextAddr->getOperand(0)->getOpcode() == ISD::TargetBlockAddress) { 268251875Speter return CurDAG->SelectNodeTo(N, XCore::BRFU_lu6, MVT::Other, 269251875Speter nextAddr->getOperand(0), Glue); 270251875Speter } 271251875Speter return CurDAG->SelectNodeTo(N, XCore::BAU_1r, MVT::Other, nextAddr, Glue); 272251875Speter} 273251875Speter