1//===-- LanaiISelDAGToDAG.cpp - A dag to dag inst selector for Lanai ------===// 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 Lanai target. 11// 12//===----------------------------------------------------------------------===// 13 14#include "Lanai.h" 15#include "LanaiMachineFunctionInfo.h" 16#include "LanaiRegisterInfo.h" 17#include "LanaiSubtarget.h" 18#include "LanaiTargetMachine.h" 19#include "llvm/CodeGen/MachineConstantPool.h" 20#include "llvm/CodeGen/MachineFrameInfo.h" 21#include "llvm/CodeGen/MachineFunction.h" 22#include "llvm/CodeGen/MachineInstrBuilder.h" 23#include "llvm/CodeGen/MachineRegisterInfo.h" 24#include "llvm/CodeGen/SelectionDAGISel.h" 25#include "llvm/IR/CFG.h" 26#include "llvm/IR/GlobalValue.h" 27#include "llvm/IR/Instructions.h" 28#include "llvm/IR/Intrinsics.h" 29#include "llvm/IR/Type.h" 30#include "llvm/Support/Debug.h" 31#include "llvm/Support/ErrorHandling.h" 32#include "llvm/Support/raw_ostream.h" 33#include "llvm/Target/TargetMachine.h" 34 35using namespace llvm; 36 37#define DEBUG_TYPE "lanai-isel" 38 39//===----------------------------------------------------------------------===// 40// Instruction Selector Implementation 41//===----------------------------------------------------------------------===// 42 43//===----------------------------------------------------------------------===// 44// LanaiDAGToDAGISel - Lanai specific code to select Lanai machine 45// instructions for SelectionDAG operations. 46//===----------------------------------------------------------------------===// 47namespace { 48 49class LanaiDAGToDAGISel : public SelectionDAGISel { 50public: 51 explicit LanaiDAGToDAGISel(LanaiTargetMachine &TargetMachine) 52 : SelectionDAGISel(TargetMachine) {} 53 54 bool runOnMachineFunction(MachineFunction &MF) override { 55 return SelectionDAGISel::runOnMachineFunction(MF); 56 } 57 58 // Pass Name 59 const char *getPassName() const override { 60 return "Lanai DAG->DAG Pattern Instruction Selection"; 61 } 62 63 bool SelectInlineAsmMemoryOperand(const SDValue &Op, unsigned ConstraintCode, 64 std::vector<SDValue> &OutOps) override; 65 66private: 67// Include the pieces autogenerated from the target description. 68#include "LanaiGenDAGISel.inc" 69 70 // Instruction Selection not handled by the auto-generated tablgen 71 void Select(SDNode *N) override; 72 73 // Support functions for the opcodes of Instruction Selection 74 // not handled by the auto-generated tablgen 75 void selectFrameIndex(SDNode *N); 76 77 // Complex Pattern for address selection. 78 bool selectAddrRi(SDValue Addr, SDValue &Base, SDValue &Offset, 79 SDValue &AluOp); 80 bool selectAddrRr(SDValue Addr, SDValue &R1, SDValue &R2, SDValue &AluOp); 81 bool selectAddrSls(SDValue Addr, SDValue &Offset); 82 bool selectAddrSpls(SDValue Addr, SDValue &Base, SDValue &Offset, 83 SDValue &AluOp); 84 85 // getI32Imm - Return a target constant with the specified value, of type i32. 86 inline SDValue getI32Imm(unsigned Imm, const SDLoc &DL) { 87 return CurDAG->getTargetConstant(Imm, DL, MVT::i32); 88 } 89 90private: 91 bool selectAddrRiSpls(SDValue Addr, SDValue &Base, SDValue &Offset, 92 SDValue &AluOp, bool RiMode); 93}; 94 95bool canBeRepresentedAsSls(const ConstantSDNode &CN) { 96 // Fits in 21-bit signed immediate and two low-order bits are zero. 97 return isInt<21>(CN.getSExtValue()) && ((CN.getSExtValue() & 0x3) == 0); 98} 99 100} // namespace 101 102// Helper functions for ComplexPattern used on LanaiInstrInfo 103// Used on Lanai Load/Store instructions. 104bool LanaiDAGToDAGISel::selectAddrSls(SDValue Addr, SDValue &Offset) { 105 if (ConstantSDNode *CN = dyn_cast<ConstantSDNode>(Addr)) { 106 SDLoc DL(Addr); 107 // Loading from a constant address. 108 if (canBeRepresentedAsSls(*CN)) { 109 int32_t Imm = CN->getSExtValue(); 110 Offset = CurDAG->getTargetConstant(Imm, DL, CN->getValueType(0)); 111 return true; 112 } 113 } 114 if (Addr.getOpcode() == ISD::OR && 115 Addr.getOperand(1).getOpcode() == LanaiISD::SMALL) { 116 Offset = Addr.getOperand(1).getOperand(0); 117 return true; 118 } 119 return false; 120} 121 122bool LanaiDAGToDAGISel::selectAddrRiSpls(SDValue Addr, SDValue &Base, 123 SDValue &Offset, SDValue &AluOp, 124 bool RiMode) { 125 SDLoc DL(Addr); 126 127 if (ConstantSDNode *CN = dyn_cast<ConstantSDNode>(Addr)) { 128 if (RiMode) { 129 // Fits in 16-bit signed immediate. 130 if (isInt<16>(CN->getSExtValue())) { 131 int16_t Imm = CN->getSExtValue(); 132 Offset = CurDAG->getTargetConstant(Imm, DL, CN->getValueType(0)); 133 Base = CurDAG->getRegister(Lanai::R0, CN->getValueType(0)); 134 AluOp = CurDAG->getTargetConstant(LPAC::ADD, DL, MVT::i32); 135 return true; 136 } 137 // Allow SLS to match if the constant doesn't fit in 16 bits but can be 138 // represented as an SLS. 139 if (canBeRepresentedAsSls(*CN)) 140 return false; 141 } else { 142 // Fits in 10-bit signed immediate. 143 if (isInt<10>(CN->getSExtValue())) { 144 int16_t Imm = CN->getSExtValue(); 145 Offset = CurDAG->getTargetConstant(Imm, DL, CN->getValueType(0)); 146 Base = CurDAG->getRegister(Lanai::R0, CN->getValueType(0)); 147 AluOp = CurDAG->getTargetConstant(LPAC::ADD, DL, MVT::i32); 148 return true; 149 } 150 } 151 } 152 153 // if Address is FI, get the TargetFrameIndex. 154 if (FrameIndexSDNode *FIN = dyn_cast<FrameIndexSDNode>(Addr)) { 155 Base = CurDAG->getTargetFrameIndex( 156 FIN->getIndex(), 157 getTargetLowering()->getPointerTy(CurDAG->getDataLayout())); 158 Offset = CurDAG->getTargetConstant(0, DL, MVT::i32); 159 AluOp = CurDAG->getTargetConstant(LPAC::ADD, DL, MVT::i32); 160 return true; 161 } 162 163 // Skip direct calls 164 if ((Addr.getOpcode() == ISD::TargetExternalSymbol || 165 Addr.getOpcode() == ISD::TargetGlobalAddress)) 166 return false; 167 168 // Address of the form imm + reg 169 ISD::NodeType AluOperator = static_cast<ISD::NodeType>(Addr.getOpcode()); 170 if (AluOperator == ISD::ADD) { 171 AluOp = CurDAG->getTargetConstant(LPAC::ADD, DL, MVT::i32); 172 // Addresses of the form FI+const 173 if (ConstantSDNode *CN = dyn_cast<ConstantSDNode>(Addr.getOperand(1))) 174 if ((RiMode && isInt<16>(CN->getSExtValue())) || 175 (!RiMode && isInt<10>(CN->getSExtValue()))) { 176 // If the first operand is a FI, get the TargetFI Node 177 if (FrameIndexSDNode *FIN = 178 dyn_cast<FrameIndexSDNode>(Addr.getOperand(0))) { 179 Base = CurDAG->getTargetFrameIndex( 180 FIN->getIndex(), 181 getTargetLowering()->getPointerTy(CurDAG->getDataLayout())); 182 } else { 183 Base = Addr.getOperand(0); 184 } 185 186 Offset = CurDAG->getTargetConstant(CN->getSExtValue(), DL, MVT::i32); 187 return true; 188 } 189 } 190 191 // Let SLS match SMALL instead of RI. 192 if (AluOperator == ISD::OR && RiMode && 193 Addr.getOperand(1).getOpcode() == LanaiISD::SMALL) 194 return false; 195 196 Base = Addr; 197 Offset = CurDAG->getTargetConstant(0, DL, MVT::i32); 198 AluOp = CurDAG->getTargetConstant(LPAC::ADD, DL, MVT::i32); 199 return true; 200} 201 202bool LanaiDAGToDAGISel::selectAddrRi(SDValue Addr, SDValue &Base, 203 SDValue &Offset, SDValue &AluOp) { 204 return selectAddrRiSpls(Addr, Base, Offset, AluOp, /*RImode=*/true); 205} 206 207bool LanaiDAGToDAGISel::selectAddrSpls(SDValue Addr, SDValue &Base, 208 SDValue &Offset, SDValue &AluOp) { 209 return selectAddrRiSpls(Addr, Base, Offset, AluOp, /*RiMode=*/false); 210} 211 212bool LanaiDAGToDAGISel::selectAddrRr(SDValue Addr, SDValue &R1, SDValue &R2, 213 SDValue &AluOp) { 214 // if Address is FI, get the TargetFrameIndex. 215 if (Addr.getOpcode() == ISD::FrameIndex) 216 return false; 217 218 // Skip direct calls 219 if ((Addr.getOpcode() == ISD::TargetExternalSymbol || 220 Addr.getOpcode() == ISD::TargetGlobalAddress)) 221 return false; 222 223 // Address of the form OP + OP 224 ISD::NodeType AluOperator = static_cast<ISD::NodeType>(Addr.getOpcode()); 225 LPAC::AluCode AluCode = LPAC::isdToLanaiAluCode(AluOperator); 226 if (AluCode != LPAC::UNKNOWN) { 227 // Skip addresses of the form FI OP const 228 if (ConstantSDNode *CN = dyn_cast<ConstantSDNode>(Addr.getOperand(1))) 229 if (isInt<16>(CN->getSExtValue())) 230 return false; 231 232 // Skip addresses with hi/lo operands 233 if (Addr.getOperand(0).getOpcode() == LanaiISD::HI || 234 Addr.getOperand(0).getOpcode() == LanaiISD::LO || 235 Addr.getOperand(0).getOpcode() == LanaiISD::SMALL || 236 Addr.getOperand(1).getOpcode() == LanaiISD::HI || 237 Addr.getOperand(1).getOpcode() == LanaiISD::LO || 238 Addr.getOperand(1).getOpcode() == LanaiISD::SMALL) 239 return false; 240 241 // Addresses of the form register OP register 242 R1 = Addr.getOperand(0); 243 R2 = Addr.getOperand(1); 244 AluOp = CurDAG->getTargetConstant(AluCode, SDLoc(Addr), MVT::i32); 245 return true; 246 } 247 248 // Skip addresses with zero offset 249 return false; 250} 251 252bool LanaiDAGToDAGISel::SelectInlineAsmMemoryOperand( 253 const SDValue &Op, unsigned ConstraintCode, std::vector<SDValue> &OutOps) { 254 SDValue Op0, Op1, AluOp; 255 switch (ConstraintCode) { 256 default: 257 return true; 258 case InlineAsm::Constraint_m: // memory 259 if (!selectAddrRr(Op, Op0, Op1, AluOp) && 260 !selectAddrRi(Op, Op0, Op1, AluOp)) 261 return true; 262 break; 263 } 264 265 OutOps.push_back(Op0); 266 OutOps.push_back(Op1); 267 OutOps.push_back(AluOp); 268 return false; 269} 270 271// Select instructions not customized! Used for 272// expanded, promoted and normal instructions 273void LanaiDAGToDAGISel::Select(SDNode *Node) { 274 unsigned Opcode = Node->getOpcode(); 275 276 // Dump information about the Node being selected 277 DEBUG(errs() << "Selecting: "; Node->dump(CurDAG); errs() << "\n"); 278 279 // If we have a custom node, we already have selected! 280 if (Node->isMachineOpcode()) { 281 DEBUG(errs() << "== "; Node->dump(CurDAG); errs() << "\n"); 282 return; 283 } 284 285 // Instruction Selection not handled by the auto-generated 286 // tablegen selection should be handled here. 287 switch (Opcode) { 288 case ISD::FrameIndex: 289 selectFrameIndex(Node); 290 return; 291 default: 292 break; 293 } 294 295 // Select the default instruction 296 SelectCode(Node); 297} 298 299void LanaiDAGToDAGISel::selectFrameIndex(SDNode *Node) { 300 SDLoc DL(Node); 301 SDValue Imm = CurDAG->getTargetConstant(0, DL, MVT::i32); 302 int FI = dyn_cast<FrameIndexSDNode>(Node)->getIndex(); 303 EVT VT = Node->getValueType(0); 304 SDValue TFI = CurDAG->getTargetFrameIndex(FI, VT); 305 unsigned Opc = Lanai::ADD_I_LO; 306 if (Node->hasOneUse()) { 307 CurDAG->SelectNodeTo(Node, Opc, VT, TFI, Imm); 308 return; 309 } 310 ReplaceNode(Node, CurDAG->getMachineNode(Opc, DL, VT, TFI, Imm)); 311} 312 313// createLanaiISelDag - This pass converts a legalized DAG into a 314// Lanai-specific DAG, ready for instruction scheduling. 315FunctionPass *llvm::createLanaiISelDag(LanaiTargetMachine &TM) { 316 return new LanaiDAGToDAGISel(TM); 317} 318