1 //===-- XCoreISelDAGToDAG.cpp - A dag to dag inst selector for XCore ------===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 // 10 // This file defines an instruction selector for the XCore target. 11 // 12 //===----------------------------------------------------------------------===// 13 14 #include "XCore.h" 15 #include "XCoreISelLowering.h" 16 #include "XCoreTargetMachine.h" 17 #include "llvm/DerivedTypes.h" 18 #include "llvm/Function.h" 19 #include "llvm/Intrinsics.h" 20 #include "llvm/CallingConv.h" 21 #include "llvm/Constants.h" 22 #include "llvm/CodeGen/MachineFrameInfo.h" 23 #include "llvm/CodeGen/MachineFunction.h" 24 #include "llvm/CodeGen/MachineInstrBuilder.h" 25 #include "llvm/CodeGen/MachineRegisterInfo.h" 26 #include "llvm/CodeGen/SelectionDAG.h" 27 #include "llvm/CodeGen/SelectionDAGISel.h" 28 #include "llvm/Target/TargetLowering.h" 29 #include "llvm/Support/Compiler.h" 30 #include "llvm/Support/Debug.h" 31 #include <queue> 32 #include <set> 33 using namespace llvm; 34 35 /// XCoreDAGToDAGISel - XCore specific code to select XCore machine 36 /// instructions for SelectionDAG operations. 37 /// 38 namespace { 39 class XCoreDAGToDAGISel : public SelectionDAGISel { 40 XCoreTargetLowering &Lowering; 41 const XCoreSubtarget &Subtarget; 42 43 public: 44 XCoreDAGToDAGISel(XCoreTargetMachine &TM) 45 : SelectionDAGISel(TM), 46 Lowering(*TM.getTargetLowering()), 47 Subtarget(*TM.getSubtargetImpl()) { } 48 49 SDNode *Select(SDValue Op); 50 51 /// getI32Imm - Return a target constant with the specified value, of type 52 /// i32. 53 inline SDValue getI32Imm(unsigned Imm) { 54 return CurDAG->getTargetConstant(Imm, MVT::i32); 55 } 56 57 // Complex Pattern Selectors. 58 bool SelectADDRspii(SDValue Op, SDValue Addr, SDValue &Base, 59 SDValue &Offset); 60 bool SelectADDRdpii(SDValue Op, SDValue Addr, SDValue &Base, 61 SDValue &Offset); 62 bool SelectADDRcpii(SDValue Op, SDValue Addr, SDValue &Base, 63 SDValue &Offset); 64 65 virtual void InstructionSelect(); 66 67 virtual const char *getPassName() const { 68 return "XCore DAG->DAG Pattern Instruction Selection"; 69 } 70 71 // Include the pieces autogenerated from the target description. 72 #include "XCoreGenDAGISel.inc" 73 }; 74 } // end anonymous namespace 75 76 /// createXCoreISelDag - This pass converts a legalized DAG into a 77 /// XCore-specific DAG, ready for instruction scheduling. 78 /// 79 FunctionPass *llvm::createXCoreISelDag(XCoreTargetMachine &TM) { 80 return new XCoreDAGToDAGISel(TM); 81 } 82 83 bool XCoreDAGToDAGISel::SelectADDRspii(SDValue Op, SDValue Addr, 84 SDValue &Base, SDValue &Offset) { 85 FrameIndexSDNode *FIN = 0; 86 if ((FIN = dyn_cast<FrameIndexSDNode>(Addr))) { 87 Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), MVT::i32); 88 Offset = CurDAG->getTargetConstant(0, MVT::i32); 89 return true; 90 } 91 if (Addr.getOpcode() == ISD::ADD) { 92 ConstantSDNode *CN = 0; 93 if ((FIN = dyn_cast<FrameIndexSDNode>(Addr.getOperand(0))) 94 && (CN = dyn_cast<ConstantSDNode>(Addr.getOperand(1))) 95 && (CN->getSExtValue() % 4 == 0 && CN->getSExtValue() >= 0)) { 96 // Constant positive word offset from frame index 97 Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), MVT::i32); 98 Offset = CurDAG->getTargetConstant(CN->getSExtValue(), MVT::i32); 99 return true; 100 } 101 } 102 return false; 103 } 104 105 bool XCoreDAGToDAGISel::SelectADDRdpii(SDValue Op, SDValue Addr, 106 SDValue &Base, SDValue &Offset) { 107 if (Addr.getOpcode() == XCoreISD::DPRelativeWrapper) { 108 Base = Addr.getOperand(0); 109 Offset = CurDAG->getTargetConstant(0, MVT::i32); 110 return true; 111 } 112 if (Addr.getOpcode() == ISD::ADD) { 113 ConstantSDNode *CN = 0; 114 if ((Addr.getOperand(0).getOpcode() == XCoreISD::DPRelativeWrapper) 115 && (CN = dyn_cast<ConstantSDNode>(Addr.getOperand(1))) 116 && (CN->getSExtValue() % 4 == 0)) { 117 // Constant word offset from a object in the data region 118 Base = Addr.getOperand(0).getOperand(0); 119 Offset = CurDAG->getTargetConstant(CN->getSExtValue(), MVT::i32); 120 return true; 121 } 122 } 123 return false; 124 } 125 126 bool XCoreDAGToDAGISel::SelectADDRcpii(SDValue Op, SDValue Addr, 127 SDValue &Base, SDValue &Offset) { 128 if (Addr.getOpcode() == XCoreISD::CPRelativeWrapper) { 129 Base = Addr.getOperand(0); 130 Offset = CurDAG->getTargetConstant(0, MVT::i32); 131 return true; 132 } 133 if (Addr.getOpcode() == ISD::ADD) { 134 ConstantSDNode *CN = 0; 135 if ((Addr.getOperand(0).getOpcode() == XCoreISD::CPRelativeWrapper) 136 && (CN = dyn_cast<ConstantSDNode>(Addr.getOperand(1))) 137 && (CN->getSExtValue() % 4 == 0)) { 138 // Constant word offset from a object in the data region 139 Base = Addr.getOperand(0).getOperand(0); 140 Offset = CurDAG->getTargetConstant(CN->getSExtValue(), MVT::i32); 141 return true; 142 } 143 } 144 return false; 145 } 146 147 /// InstructionSelect - This callback is invoked by 148 /// SelectionDAGISel when it has created a SelectionDAG for us to codegen. 149 void XCoreDAGToDAGISel:: 150 InstructionSelect() { 151 DEBUG(BB->dump()); 152 153 // Select target instructions for the DAG. 154 SelectRoot(*CurDAG); 155 156 CurDAG->RemoveDeadNodes(); 157 } 158 159 SDNode *XCoreDAGToDAGISel::Select(SDValue Op) { 160 SDNode *N = Op.getNode(); 161 DebugLoc dl = N->getDebugLoc(); 162 MVT NVT = N->getValueType(0); 163 if (NVT == MVT::i32) { 164 switch (N->getOpcode()) { 165 default: break; 166 case ISD::Constant: { 167 if (Predicate_immMskBitp(N)) { 168 SDValue MskSize = Transform_msksize_xform(N); 169 return CurDAG->getTargetNode(XCore::MKMSK_rus, dl, MVT::i32, MskSize); 170 } 171 else if (! Predicate_immU16(N)) { 172 unsigned Val = cast<ConstantSDNode>(N)->getZExtValue(); 173 SDValue CPIdx = 174 CurDAG->getTargetConstantPool(ConstantInt::get(Type::Int32Ty, Val), 175 TLI.getPointerTy()); 176 return CurDAG->getTargetNode(XCore::LDWCP_lru6, dl, MVT::i32, 177 MVT::Other, CPIdx, 178 CurDAG->getEntryNode()); 179 } 180 break; 181 } 182 case ISD::SMUL_LOHI: { 183 // FIXME fold addition into the macc instruction 184 if (!Subtarget.isXS1A()) { 185 SDValue Zero(CurDAG->getTargetNode(XCore::LDC_ru6, dl, MVT::i32, 186 CurDAG->getTargetConstant(0, MVT::i32)), 0); 187 SDValue Ops[] = { Zero, Zero, Op.getOperand(0), Op.getOperand(1) }; 188 SDNode *ResNode = CurDAG->getTargetNode(XCore::MACCS_l4r, dl, 189 MVT::i32, MVT::i32, Ops, 4); 190 ReplaceUses(SDValue(N, 0), SDValue(ResNode, 1)); 191 ReplaceUses(SDValue(N, 1), SDValue(ResNode, 0)); 192 return NULL; 193 } 194 break; 195 } 196 case ISD::UMUL_LOHI: { 197 // FIXME fold addition into the macc / lmul instruction 198 SDValue Zero(CurDAG->getTargetNode(XCore::LDC_ru6, dl, MVT::i32, 199 CurDAG->getTargetConstant(0, MVT::i32)), 0); 200 SDValue Ops[] = { Op.getOperand(0), Op.getOperand(1), 201 Zero, Zero }; 202 SDNode *ResNode = CurDAG->getTargetNode(XCore::LMUL_l6r, dl, MVT::i32, 203 MVT::i32, Ops, 4); 204 ReplaceUses(SDValue(N, 0), SDValue(ResNode, 1)); 205 ReplaceUses(SDValue(N, 1), SDValue(ResNode, 0)); 206 return NULL; 207 } 208 case XCoreISD::LADD: { 209 if (!Subtarget.isXS1A()) { 210 SDValue Ops[] = { Op.getOperand(0), Op.getOperand(1), 211 Op.getOperand(2) }; 212 return CurDAG->getTargetNode(XCore::LADD_l5r, dl, MVT::i32, MVT::i32, 213 Ops, 3); 214 } 215 break; 216 } 217 case XCoreISD::LSUB: { 218 if (!Subtarget.isXS1A()) { 219 SDValue Ops[] = { Op.getOperand(0), Op.getOperand(1), 220 Op.getOperand(2) }; 221 return CurDAG->getTargetNode(XCore::LSUB_l5r, dl, MVT::i32, MVT::i32, 222 Ops, 3); 223 } 224 break; 225 } 226 // Other cases are autogenerated. 227 } 228 } 229 return SelectCode(Op); 230 } 231