LLVM API Documentation
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 "XCoreTargetMachine.h" 00016 #include "llvm/CodeGen/MachineFrameInfo.h" 00017 #include "llvm/CodeGen/MachineFunction.h" 00018 #include "llvm/CodeGen/MachineInstrBuilder.h" 00019 #include "llvm/CodeGen/MachineRegisterInfo.h" 00020 #include "llvm/CodeGen/SelectionDAG.h" 00021 #include "llvm/CodeGen/SelectionDAGISel.h" 00022 #include "llvm/IR/CallingConv.h" 00023 #include "llvm/IR/Constants.h" 00024 #include "llvm/IR/DerivedTypes.h" 00025 #include "llvm/IR/Function.h" 00026 #include "llvm/IR/Intrinsics.h" 00027 #include "llvm/IR/LLVMContext.h" 00028 #include "llvm/Support/Compiler.h" 00029 #include "llvm/Support/Debug.h" 00030 #include "llvm/Support/ErrorHandling.h" 00031 #include "llvm/Support/raw_ostream.h" 00032 #include "llvm/Target/TargetLowering.h" 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 const XCoreSubtarget &Subtarget; 00041 00042 public: 00043 XCoreDAGToDAGISel(XCoreTargetMachine &TM, CodeGenOpt::Level OptLevel) 00044 : SelectionDAGISel(TM, OptLevel), 00045 Subtarget(*TM.getSubtargetImpl()) { } 00046 00047 SDNode *Select(SDNode *N) override; 00048 SDNode *SelectBRIND(SDNode *N); 00049 00050 /// getI32Imm - Return a target constant with the specified value, of type 00051 /// i32. 00052 inline SDValue getI32Imm(unsigned Imm) { 00053 return CurDAG->getTargetConstant(Imm, MVT::i32); 00054 } 00055 00056 inline bool immMskBitp(SDNode *inN) const { 00057 ConstantSDNode *N = cast<ConstantSDNode>(inN); 00058 uint32_t value = (uint32_t)N->getZExtValue(); 00059 if (!isMask_32(value)) { 00060 return false; 00061 } 00062 int msksize = 32 - countLeadingZeros(value); 00063 return (msksize >= 1 && msksize <= 8) || 00064 msksize == 16 || msksize == 24 || msksize == 32; 00065 } 00066 00067 // Complex Pattern Selectors. 00068 bool SelectADDRspii(SDValue Addr, SDValue &Base, SDValue &Offset); 00069 00070 bool SelectInlineAsmMemoryOperand(const SDValue &Op, char ConstraintCode, 00071 std::vector<SDValue> &OutOps) override; 00072 00073 const char *getPassName() const override { 00074 return "XCore DAG->DAG Pattern Instruction Selection"; 00075 } 00076 00077 // Include the pieces autogenerated from the target description. 00078 #include "XCoreGenDAGISel.inc" 00079 }; 00080 } // end anonymous namespace 00081 00082 /// createXCoreISelDag - This pass converts a legalized DAG into a 00083 /// XCore-specific DAG, ready for instruction scheduling. 00084 /// 00085 FunctionPass *llvm::createXCoreISelDag(XCoreTargetMachine &TM, 00086 CodeGenOpt::Level OptLevel) { 00087 return new XCoreDAGToDAGISel(TM, OptLevel); 00088 } 00089 00090 bool XCoreDAGToDAGISel::SelectADDRspii(SDValue Addr, SDValue &Base, 00091 SDValue &Offset) { 00092 FrameIndexSDNode *FIN = nullptr; 00093 if ((FIN = dyn_cast<FrameIndexSDNode>(Addr))) { 00094 Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), MVT::i32); 00095 Offset = CurDAG->getTargetConstant(0, MVT::i32); 00096 return true; 00097 } 00098 if (Addr.getOpcode() == ISD::ADD) { 00099 ConstantSDNode *CN = nullptr; 00100 if ((FIN = dyn_cast<FrameIndexSDNode>(Addr.getOperand(0))) 00101 && (CN = dyn_cast<ConstantSDNode>(Addr.getOperand(1))) 00102 && (CN->getSExtValue() % 4 == 0 && CN->getSExtValue() >= 0)) { 00103 // Constant positive word offset from frame index 00104 Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), MVT::i32); 00105 Offset = CurDAG->getTargetConstant(CN->getSExtValue(), MVT::i32); 00106 return true; 00107 } 00108 } 00109 return false; 00110 } 00111 00112 bool XCoreDAGToDAGISel:: 00113 SelectInlineAsmMemoryOperand(const SDValue &Op, char ConstraintCode, 00114 std::vector<SDValue> &OutOps) { 00115 SDValue Reg; 00116 switch (ConstraintCode) { 00117 default: return true; 00118 case 'm': // Memory. 00119 switch (Op.getOpcode()) { 00120 default: return true; 00121 case XCoreISD::CPRelativeWrapper: 00122 Reg = CurDAG->getRegister(XCore::CP, MVT::i32); 00123 break; 00124 case XCoreISD::DPRelativeWrapper: 00125 Reg = CurDAG->getRegister(XCore::DP, MVT::i32); 00126 break; 00127 } 00128 } 00129 OutOps.push_back(Reg); 00130 OutOps.push_back(Op.getOperand(0)); 00131 return false; 00132 } 00133 00134 SDNode *XCoreDAGToDAGISel::Select(SDNode *N) { 00135 SDLoc dl(N); 00136 switch (N->getOpcode()) { 00137 default: break; 00138 case ISD::Constant: { 00139 uint64_t Val = cast<ConstantSDNode>(N)->getZExtValue(); 00140 if (immMskBitp(N)) { 00141 // Transformation function: get the size of a mask 00142 // Look for the first non-zero bit 00143 SDValue MskSize = getI32Imm(32 - countLeadingZeros((uint32_t)Val)); 00144 return CurDAG->getMachineNode(XCore::MKMSK_rus, dl, 00145 MVT::i32, MskSize); 00146 } 00147 else if (!isUInt<16>(Val)) { 00148 SDValue CPIdx = 00149 CurDAG->getTargetConstantPool(ConstantInt::get( 00150 Type::getInt32Ty(*CurDAG->getContext()), Val), 00151 getTargetLowering()->getPointerTy()); 00152 SDNode *node = CurDAG->getMachineNode(XCore::LDWCP_lru6, dl, MVT::i32, 00153 MVT::Other, CPIdx, 00154 CurDAG->getEntryNode()); 00155 MachineSDNode::mmo_iterator MemOp = MF->allocateMemRefsArray(1); 00156 MemOp[0] = MF->getMachineMemOperand( 00157 MachinePointerInfo::getConstantPool(), MachineMemOperand::MOLoad, 4, 4); 00158 cast<MachineSDNode>(node)->setMemRefs(MemOp, MemOp + 1); 00159 return node; 00160 } 00161 break; 00162 } 00163 case XCoreISD::LADD: { 00164 SDValue Ops[] = { N->getOperand(0), N->getOperand(1), 00165 N->getOperand(2) }; 00166 return CurDAG->getMachineNode(XCore::LADD_l5r, dl, MVT::i32, MVT::i32, 00167 Ops); 00168 } 00169 case XCoreISD::LSUB: { 00170 SDValue Ops[] = { N->getOperand(0), N->getOperand(1), 00171 N->getOperand(2) }; 00172 return CurDAG->getMachineNode(XCore::LSUB_l5r, dl, MVT::i32, MVT::i32, 00173 Ops); 00174 } 00175 case XCoreISD::MACCU: { 00176 SDValue Ops[] = { N->getOperand(0), N->getOperand(1), 00177 N->getOperand(2), N->getOperand(3) }; 00178 return CurDAG->getMachineNode(XCore::MACCU_l4r, dl, MVT::i32, MVT::i32, 00179 Ops); 00180 } 00181 case XCoreISD::MACCS: { 00182 SDValue Ops[] = { N->getOperand(0), N->getOperand(1), 00183 N->getOperand(2), N->getOperand(3) }; 00184 return CurDAG->getMachineNode(XCore::MACCS_l4r, dl, MVT::i32, MVT::i32, 00185 Ops); 00186 } 00187 case XCoreISD::LMUL: { 00188 SDValue Ops[] = { N->getOperand(0), N->getOperand(1), 00189 N->getOperand(2), N->getOperand(3) }; 00190 return CurDAG->getMachineNode(XCore::LMUL_l6r, dl, MVT::i32, MVT::i32, 00191 Ops); 00192 } 00193 case XCoreISD::CRC8: { 00194 SDValue Ops[] = { N->getOperand(0), N->getOperand(1), N->getOperand(2) }; 00195 return CurDAG->getMachineNode(XCore::CRC8_l4r, dl, MVT::i32, MVT::i32, 00196 Ops); 00197 } 00198 case ISD::BRIND: 00199 if (SDNode *ResNode = SelectBRIND(N)) 00200 return ResNode; 00201 break; 00202 // Other cases are autogenerated. 00203 } 00204 return SelectCode(N); 00205 } 00206 00207 /// Given a chain return a new chain where any appearance of Old is replaced 00208 /// by New. There must be at most one instruction between Old and Chain and 00209 /// this instruction must be a TokenFactor. Returns an empty SDValue if 00210 /// these conditions don't hold. 00211 static SDValue 00212 replaceInChain(SelectionDAG *CurDAG, SDValue Chain, SDValue Old, SDValue New) 00213 { 00214 if (Chain == Old) 00215 return New; 00216 if (Chain->getOpcode() != ISD::TokenFactor) 00217 return SDValue(); 00218 SmallVector<SDValue, 8> Ops; 00219 bool found = false; 00220 for (unsigned i = 0, e = Chain->getNumOperands(); i != e; ++i) { 00221 if (Chain->getOperand(i) == Old) { 00222 Ops.push_back(New); 00223 found = true; 00224 } else { 00225 Ops.push_back(Chain->getOperand(i)); 00226 } 00227 } 00228 if (!found) 00229 return SDValue(); 00230 return CurDAG->getNode(ISD::TokenFactor, SDLoc(Chain), MVT::Other, Ops); 00231 } 00232 00233 SDNode *XCoreDAGToDAGISel::SelectBRIND(SDNode *N) { 00234 SDLoc dl(N); 00235 // (brind (int_xcore_checkevent (addr))) 00236 SDValue Chain = N->getOperand(0); 00237 SDValue Addr = N->getOperand(1); 00238 if (Addr->getOpcode() != ISD::INTRINSIC_W_CHAIN) 00239 return nullptr; 00240 unsigned IntNo = cast<ConstantSDNode>(Addr->getOperand(1))->getZExtValue(); 00241 if (IntNo != Intrinsic::xcore_checkevent) 00242 return nullptr; 00243 SDValue nextAddr = Addr->getOperand(2); 00244 SDValue CheckEventChainOut(Addr.getNode(), 1); 00245 if (!CheckEventChainOut.use_empty()) { 00246 // If the chain out of the checkevent intrinsic is an operand of the 00247 // indirect branch or used in a TokenFactor which is the operand of the 00248 // indirect branch then build a new chain which uses the chain coming into 00249 // the checkevent intrinsic instead. 00250 SDValue CheckEventChainIn = Addr->getOperand(0); 00251 SDValue NewChain = replaceInChain(CurDAG, Chain, CheckEventChainOut, 00252 CheckEventChainIn); 00253 if (!NewChain.getNode()) 00254 return nullptr; 00255 Chain = NewChain; 00256 } 00257 // Enable events on the thread using setsr 1 and then disable them immediately 00258 // after with clrsr 1. If any resources owned by the thread are ready an event 00259 // will be taken. If no resource is ready we branch to the address which was 00260 // the operand to the checkevent intrinsic. 00261 SDValue constOne = getI32Imm(1); 00262 SDValue Glue = 00263 SDValue(CurDAG->getMachineNode(XCore::SETSR_branch_u6, dl, MVT::Glue, 00264 constOne, Chain), 0); 00265 Glue = 00266 SDValue(CurDAG->getMachineNode(XCore::CLRSR_branch_u6, dl, MVT::Glue, 00267 constOne, Glue), 0); 00268 if (nextAddr->getOpcode() == XCoreISD::PCRelativeWrapper && 00269 nextAddr->getOperand(0)->getOpcode() == ISD::TargetBlockAddress) { 00270 return CurDAG->SelectNodeTo(N, XCore::BRFU_lu6, MVT::Other, 00271 nextAddr->getOperand(0), Glue); 00272 } 00273 return CurDAG->SelectNodeTo(N, XCore::BAU_1r, MVT::Other, nextAddr, Glue); 00274 }