LLVM API Documentation

XCoreISelDAGToDAG.cpp
Go to the documentation of this file.
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 }