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