1 //===-- LanaiISelDAGToDAG.cpp - A dag to dag inst selector for Lanai ------===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 // 9 // This file defines an instruction selector for the Lanai target. 10 // 11 //===----------------------------------------------------------------------===// 12 13 #include "LanaiAluCode.h" 14 #include "LanaiMachineFunctionInfo.h" 15 #include "LanaiRegisterInfo.h" 16 #include "LanaiSubtarget.h" 17 #include "LanaiTargetMachine.h" 18 #include "llvm/CodeGen/MachineConstantPool.h" 19 #include "llvm/CodeGen/MachineFrameInfo.h" 20 #include "llvm/CodeGen/MachineFunction.h" 21 #include "llvm/CodeGen/MachineInstrBuilder.h" 22 #include "llvm/CodeGen/MachineRegisterInfo.h" 23 #include "llvm/CodeGen/SelectionDAGISel.h" 24 #include "llvm/IR/CFG.h" 25 #include "llvm/IR/GlobalValue.h" 26 #include "llvm/IR/Instructions.h" 27 #include "llvm/IR/Intrinsics.h" 28 #include "llvm/IR/Type.h" 29 #include "llvm/Support/Debug.h" 30 #include "llvm/Support/ErrorHandling.h" 31 #include "llvm/Support/raw_ostream.h" 32 #include "llvm/Target/TargetMachine.h" 33 34 using namespace llvm; 35 36 #define DEBUG_TYPE "lanai-isel" 37 #define PASS_NAME "Lanai DAG->DAG Pattern Instruction Selection" 38 39 //===----------------------------------------------------------------------===// 40 // Instruction Selector Implementation 41 //===----------------------------------------------------------------------===// 42 43 //===----------------------------------------------------------------------===// 44 // LanaiDAGToDAGISel - Lanai specific code to select Lanai machine 45 // instructions for SelectionDAG operations. 46 //===----------------------------------------------------------------------===// 47 namespace { 48 49 class LanaiDAGToDAGISel : public SelectionDAGISel { 50 public: 51 static char ID; 52 53 LanaiDAGToDAGISel() = delete; 54 55 explicit LanaiDAGToDAGISel(LanaiTargetMachine &TargetMachine) 56 : SelectionDAGISel(ID, TargetMachine) {} 57 58 bool runOnMachineFunction(MachineFunction &MF) override { 59 return SelectionDAGISel::runOnMachineFunction(MF); 60 } 61 62 bool SelectInlineAsmMemoryOperand(const SDValue &Op, 63 InlineAsm::ConstraintCode ConstraintCode, 64 std::vector<SDValue> &OutOps) override; 65 66 private: 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 90 private: 91 bool selectAddrRiSpls(SDValue Addr, SDValue &Base, SDValue &Offset, 92 SDValue &AluOp, bool RiMode); 93 }; 94 95 bool 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 char LanaiDAGToDAGISel::ID = 0; 103 104 INITIALIZE_PASS(LanaiDAGToDAGISel, DEBUG_TYPE, PASS_NAME, false, false) 105 106 // Helper functions for ComplexPattern used on LanaiInstrInfo 107 // Used on Lanai Load/Store instructions. 108 bool LanaiDAGToDAGISel::selectAddrSls(SDValue Addr, SDValue &Offset) { 109 if (ConstantSDNode *CN = dyn_cast<ConstantSDNode>(Addr)) { 110 SDLoc DL(Addr); 111 // Loading from a constant address. 112 if (canBeRepresentedAsSls(*CN)) { 113 int32_t Imm = CN->getSExtValue(); 114 Offset = CurDAG->getTargetConstant(Imm, DL, CN->getValueType(0)); 115 return true; 116 } 117 } 118 if (Addr.getOpcode() == ISD::OR && 119 Addr.getOperand(1).getOpcode() == LanaiISD::SMALL) { 120 Offset = Addr.getOperand(1).getOperand(0); 121 return true; 122 } 123 return false; 124 } 125 126 bool LanaiDAGToDAGISel::selectAddrRiSpls(SDValue Addr, SDValue &Base, 127 SDValue &Offset, SDValue &AluOp, 128 bool RiMode) { 129 SDLoc DL(Addr); 130 131 if (ConstantSDNode *CN = dyn_cast<ConstantSDNode>(Addr)) { 132 if (RiMode) { 133 // Fits in 16-bit signed immediate. 134 if (isInt<16>(CN->getSExtValue())) { 135 int16_t Imm = CN->getSExtValue(); 136 Offset = CurDAG->getTargetConstant(Imm, DL, CN->getValueType(0)); 137 Base = CurDAG->getRegister(Lanai::R0, CN->getValueType(0)); 138 AluOp = CurDAG->getTargetConstant(LPAC::ADD, DL, MVT::i32); 139 return true; 140 } 141 // Allow SLS to match if the constant doesn't fit in 16 bits but can be 142 // represented as an SLS. 143 if (canBeRepresentedAsSls(*CN)) 144 return false; 145 } else { 146 // Fits in 10-bit signed immediate. 147 if (isInt<10>(CN->getSExtValue())) { 148 int16_t Imm = CN->getSExtValue(); 149 Offset = CurDAG->getTargetConstant(Imm, DL, CN->getValueType(0)); 150 Base = CurDAG->getRegister(Lanai::R0, CN->getValueType(0)); 151 AluOp = CurDAG->getTargetConstant(LPAC::ADD, DL, MVT::i32); 152 return true; 153 } 154 } 155 } 156 157 // if Address is FI, get the TargetFrameIndex. 158 if (FrameIndexSDNode *FIN = dyn_cast<FrameIndexSDNode>(Addr)) { 159 Base = CurDAG->getTargetFrameIndex( 160 FIN->getIndex(), 161 getTargetLowering()->getPointerTy(CurDAG->getDataLayout())); 162 Offset = CurDAG->getTargetConstant(0, DL, MVT::i32); 163 AluOp = CurDAG->getTargetConstant(LPAC::ADD, DL, MVT::i32); 164 return true; 165 } 166 167 // Skip direct calls 168 if ((Addr.getOpcode() == ISD::TargetExternalSymbol || 169 Addr.getOpcode() == ISD::TargetGlobalAddress)) 170 return false; 171 172 // Address of the form imm + reg 173 ISD::NodeType AluOperator = static_cast<ISD::NodeType>(Addr.getOpcode()); 174 if (AluOperator == ISD::ADD) { 175 AluOp = CurDAG->getTargetConstant(LPAC::ADD, DL, MVT::i32); 176 // Addresses of the form FI+const 177 if (ConstantSDNode *CN = dyn_cast<ConstantSDNode>(Addr.getOperand(1))) 178 if ((RiMode && isInt<16>(CN->getSExtValue())) || 179 (!RiMode && isInt<10>(CN->getSExtValue()))) { 180 // If the first operand is a FI, get the TargetFI Node 181 if (FrameIndexSDNode *FIN = 182 dyn_cast<FrameIndexSDNode>(Addr.getOperand(0))) { 183 Base = CurDAG->getTargetFrameIndex( 184 FIN->getIndex(), 185 getTargetLowering()->getPointerTy(CurDAG->getDataLayout())); 186 } else { 187 Base = Addr.getOperand(0); 188 } 189 190 Offset = CurDAG->getTargetConstant(CN->getSExtValue(), DL, MVT::i32); 191 return true; 192 } 193 } 194 195 // Let SLS match SMALL instead of RI. 196 if (AluOperator == ISD::OR && RiMode && 197 Addr.getOperand(1).getOpcode() == LanaiISD::SMALL) 198 return false; 199 200 Base = Addr; 201 Offset = CurDAG->getTargetConstant(0, DL, MVT::i32); 202 AluOp = CurDAG->getTargetConstant(LPAC::ADD, DL, MVT::i32); 203 return true; 204 } 205 206 bool LanaiDAGToDAGISel::selectAddrRi(SDValue Addr, SDValue &Base, 207 SDValue &Offset, SDValue &AluOp) { 208 return selectAddrRiSpls(Addr, Base, Offset, AluOp, /*RiMode=*/true); 209 } 210 211 bool LanaiDAGToDAGISel::selectAddrSpls(SDValue Addr, SDValue &Base, 212 SDValue &Offset, SDValue &AluOp) { 213 return selectAddrRiSpls(Addr, Base, Offset, AluOp, /*RiMode=*/false); 214 } 215 216 namespace llvm { 217 namespace LPAC { 218 static AluCode isdToLanaiAluCode(ISD::NodeType Node_type) { 219 switch (Node_type) { 220 case ISD::ADD: 221 return AluCode::ADD; 222 case ISD::ADDE: 223 return AluCode::ADDC; 224 case ISD::SUB: 225 return AluCode::SUB; 226 case ISD::SUBE: 227 return AluCode::SUBB; 228 case ISD::AND: 229 return AluCode::AND; 230 case ISD::OR: 231 return AluCode::OR; 232 case ISD::XOR: 233 return AluCode::XOR; 234 case ISD::SHL: 235 return AluCode::SHL; 236 case ISD::SRL: 237 return AluCode::SRL; 238 case ISD::SRA: 239 return AluCode::SRA; 240 default: 241 return AluCode::UNKNOWN; 242 } 243 } 244 } // namespace LPAC 245 } // namespace llvm 246 247 bool LanaiDAGToDAGISel::selectAddrRr(SDValue Addr, SDValue &R1, SDValue &R2, 248 SDValue &AluOp) { 249 // if Address is FI, get the TargetFrameIndex. 250 if (Addr.getOpcode() == ISD::FrameIndex) 251 return false; 252 253 // Skip direct calls 254 if ((Addr.getOpcode() == ISD::TargetExternalSymbol || 255 Addr.getOpcode() == ISD::TargetGlobalAddress)) 256 return false; 257 258 // Address of the form OP + OP 259 ISD::NodeType AluOperator = static_cast<ISD::NodeType>(Addr.getOpcode()); 260 LPAC::AluCode AluCode = LPAC::isdToLanaiAluCode(AluOperator); 261 if (AluCode != LPAC::UNKNOWN) { 262 // Skip addresses of the form FI OP const 263 if (ConstantSDNode *CN = dyn_cast<ConstantSDNode>(Addr.getOperand(1))) 264 if (isInt<16>(CN->getSExtValue())) 265 return false; 266 267 // Skip addresses with hi/lo operands 268 if (Addr.getOperand(0).getOpcode() == LanaiISD::HI || 269 Addr.getOperand(0).getOpcode() == LanaiISD::LO || 270 Addr.getOperand(0).getOpcode() == LanaiISD::SMALL || 271 Addr.getOperand(1).getOpcode() == LanaiISD::HI || 272 Addr.getOperand(1).getOpcode() == LanaiISD::LO || 273 Addr.getOperand(1).getOpcode() == LanaiISD::SMALL) 274 return false; 275 276 // Addresses of the form register OP register 277 R1 = Addr.getOperand(0); 278 R2 = Addr.getOperand(1); 279 AluOp = CurDAG->getTargetConstant(AluCode, SDLoc(Addr), MVT::i32); 280 return true; 281 } 282 283 // Skip addresses with zero offset 284 return false; 285 } 286 287 bool LanaiDAGToDAGISel::SelectInlineAsmMemoryOperand( 288 const SDValue &Op, InlineAsm::ConstraintCode ConstraintCode, 289 std::vector<SDValue> &OutOps) { 290 SDValue Op0, Op1, AluOp; 291 switch (ConstraintCode) { 292 default: 293 return true; 294 case InlineAsm::ConstraintCode::m: // memory 295 if (!selectAddrRr(Op, Op0, Op1, AluOp) && 296 !selectAddrRi(Op, Op0, Op1, AluOp)) 297 return true; 298 break; 299 } 300 301 OutOps.push_back(Op0); 302 OutOps.push_back(Op1); 303 OutOps.push_back(AluOp); 304 return false; 305 } 306 307 // Select instructions not customized! Used for 308 // expanded, promoted and normal instructions 309 void LanaiDAGToDAGISel::Select(SDNode *Node) { 310 unsigned Opcode = Node->getOpcode(); 311 312 // If we have a custom node, we already have selected! 313 if (Node->isMachineOpcode()) { 314 LLVM_DEBUG(errs() << "== "; Node->dump(CurDAG); errs() << "\n"); 315 return; 316 } 317 318 // Instruction Selection not handled by the auto-generated tablegen selection 319 // should be handled here. 320 EVT VT = Node->getValueType(0); 321 switch (Opcode) { 322 case ISD::Constant: 323 if (VT == MVT::i32) { 324 ConstantSDNode *ConstNode = cast<ConstantSDNode>(Node); 325 // Materialize zero constants as copies from R0. This allows the coalescer 326 // to propagate these into other instructions. 327 if (ConstNode->isZero()) { 328 SDValue New = CurDAG->getCopyFromReg(CurDAG->getEntryNode(), 329 SDLoc(Node), Lanai::R0, MVT::i32); 330 return ReplaceNode(Node, New.getNode()); 331 } 332 // Materialize all ones constants as copies from R1. This allows the 333 // coalescer to propagate these into other instructions. 334 if (ConstNode->isAllOnes()) { 335 SDValue New = CurDAG->getCopyFromReg(CurDAG->getEntryNode(), 336 SDLoc(Node), Lanai::R1, MVT::i32); 337 return ReplaceNode(Node, New.getNode()); 338 } 339 } 340 break; 341 case ISD::FrameIndex: 342 selectFrameIndex(Node); 343 return; 344 default: 345 break; 346 } 347 348 // Select the default instruction 349 SelectCode(Node); 350 } 351 352 void LanaiDAGToDAGISel::selectFrameIndex(SDNode *Node) { 353 SDLoc DL(Node); 354 SDValue Imm = CurDAG->getTargetConstant(0, DL, MVT::i32); 355 int FI = cast<FrameIndexSDNode>(Node)->getIndex(); 356 EVT VT = Node->getValueType(0); 357 SDValue TFI = CurDAG->getTargetFrameIndex(FI, VT); 358 unsigned Opc = Lanai::ADD_I_LO; 359 if (Node->hasOneUse()) { 360 CurDAG->SelectNodeTo(Node, Opc, VT, TFI, Imm); 361 return; 362 } 363 ReplaceNode(Node, CurDAG->getMachineNode(Opc, DL, VT, TFI, Imm)); 364 } 365 366 // createLanaiISelDag - This pass converts a legalized DAG into a 367 // Lanai-specific DAG, ready for instruction scheduling. 368 FunctionPass *llvm::createLanaiISelDag(LanaiTargetMachine &TM) { 369 return new LanaiDAGToDAGISel(TM); 370 } 371