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