1 //=- LoongArchISelLowering.cpp - LoongArch DAG Lowering Implementation ---===// 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 the interfaces that LoongArch uses to lower LLVM code into 10 // a selection DAG. 11 // 12 //===----------------------------------------------------------------------===// 13 14 #include "LoongArchISelLowering.h" 15 #include "LoongArch.h" 16 #include "LoongArchMachineFunctionInfo.h" 17 #include "LoongArchRegisterInfo.h" 18 #include "LoongArchSubtarget.h" 19 #include "LoongArchTargetMachine.h" 20 #include "MCTargetDesc/LoongArchMCTargetDesc.h" 21 #include "llvm/ADT/Statistic.h" 22 #include "llvm/CodeGen/ISDOpcodes.h" 23 #include "llvm/Support/Debug.h" 24 25 using namespace llvm; 26 27 #define DEBUG_TYPE "loongarch-isel-lowering" 28 29 LoongArchTargetLowering::LoongArchTargetLowering(const TargetMachine &TM, 30 const LoongArchSubtarget &STI) 31 : TargetLowering(TM), Subtarget(STI) { 32 33 MVT GRLenVT = Subtarget.getGRLenVT(); 34 // Set up the register classes. 35 addRegisterClass(GRLenVT, &LoongArch::GPRRegClass); 36 if (Subtarget.hasBasicF()) 37 addRegisterClass(MVT::f32, &LoongArch::FPR32RegClass); 38 if (Subtarget.hasBasicD()) 39 addRegisterClass(MVT::f64, &LoongArch::FPR64RegClass); 40 41 setLoadExtAction({ISD::EXTLOAD, ISD::SEXTLOAD, ISD::ZEXTLOAD}, GRLenVT, 42 MVT::i1, Promote); 43 44 // TODO: add necessary setOperationAction calls later. 45 setOperationAction(ISD::SHL_PARTS, GRLenVT, Custom); 46 setOperationAction(ISD::SRA_PARTS, GRLenVT, Custom); 47 setOperationAction(ISD::SRL_PARTS, GRLenVT, Custom); 48 49 setOperationAction(ISD::GlobalAddress, GRLenVT, Custom); 50 51 if (Subtarget.is64Bit()) { 52 setOperationAction(ISD::SHL, MVT::i32, Custom); 53 setOperationAction(ISD::SRA, MVT::i32, Custom); 54 setOperationAction(ISD::SRL, MVT::i32, Custom); 55 } 56 57 static const ISD::CondCode FPCCToExpand[] = {ISD::SETOGT, ISD::SETOGE, 58 ISD::SETUGT, ISD::SETUGE}; 59 60 if (Subtarget.hasBasicF()) { 61 setCondCodeAction(FPCCToExpand, MVT::f32, Expand); 62 setOperationAction(ISD::SELECT_CC, MVT::f32, Expand); 63 } 64 if (Subtarget.hasBasicD()) { 65 setCondCodeAction(FPCCToExpand, MVT::f64, Expand); 66 setOperationAction(ISD::SELECT_CC, MVT::f64, Expand); 67 } 68 69 setOperationAction(ISD::BR_CC, GRLenVT, Expand); 70 setOperationAction(ISD::SELECT_CC, GRLenVT, Expand); 71 setOperationAction(ISD::SIGN_EXTEND_INREG, MVT::i1, Expand); 72 73 // Compute derived properties from the register classes. 74 computeRegisterProperties(STI.getRegisterInfo()); 75 76 setStackPointerRegisterToSaveRestore(LoongArch::R3); 77 78 setBooleanContents(ZeroOrOneBooleanContent); 79 80 // Function alignments. 81 const Align FunctionAlignment(4); 82 setMinFunctionAlignment(FunctionAlignment); 83 84 setTargetDAGCombine(ISD::AND); 85 setTargetDAGCombine(ISD::SRL); 86 } 87 88 SDValue LoongArchTargetLowering::LowerOperation(SDValue Op, 89 SelectionDAG &DAG) const { 90 switch (Op.getOpcode()) { 91 default: 92 report_fatal_error("unimplemented operand"); 93 case ISD::GlobalAddress: 94 return lowerGlobalAddress(Op, DAG); 95 case ISD::SHL_PARTS: 96 return lowerShiftLeftParts(Op, DAG); 97 case ISD::SRA_PARTS: 98 return lowerShiftRightParts(Op, DAG, true); 99 case ISD::SRL_PARTS: 100 return lowerShiftRightParts(Op, DAG, false); 101 case ISD::SHL: 102 case ISD::SRA: 103 case ISD::SRL: 104 // This can be called for an i32 shift amount that needs to be promoted. 105 assert(Op.getOperand(1).getValueType() == MVT::i32 && Subtarget.is64Bit() && 106 "Unexpected custom legalisation"); 107 return SDValue(); 108 } 109 } 110 111 SDValue LoongArchTargetLowering::lowerGlobalAddress(SDValue Op, 112 SelectionDAG &DAG) const { 113 SDLoc DL(Op); 114 EVT Ty = getPointerTy(DAG.getDataLayout()); 115 const GlobalValue *GV = cast<GlobalAddressSDNode>(Op)->getGlobal(); 116 unsigned ADDIOp = Subtarget.is64Bit() ? LoongArch::ADDI_D : LoongArch::ADDI_W; 117 118 // FIXME: Only support PC-relative addressing to access the symbol. 119 // TODO: Add target flags. 120 if (!isPositionIndependent()) { 121 SDValue GA = DAG.getTargetGlobalAddress(GV, DL, Ty); 122 SDValue AddrHi(DAG.getMachineNode(LoongArch::PCALAU12I, DL, Ty, GA), 0); 123 SDValue Addr(DAG.getMachineNode(ADDIOp, DL, Ty, AddrHi, GA), 0); 124 return Addr; 125 } 126 report_fatal_error("Unable to lowerGlobalAddress"); 127 } 128 129 SDValue LoongArchTargetLowering::lowerShiftLeftParts(SDValue Op, 130 SelectionDAG &DAG) const { 131 SDLoc DL(Op); 132 SDValue Lo = Op.getOperand(0); 133 SDValue Hi = Op.getOperand(1); 134 SDValue Shamt = Op.getOperand(2); 135 EVT VT = Lo.getValueType(); 136 137 // if Shamt-GRLen < 0: // Shamt < GRLen 138 // Lo = Lo << Shamt 139 // Hi = (Hi << Shamt) | ((Lo >>u 1) >>u (GRLen-1 ^ Shamt)) 140 // else: 141 // Lo = 0 142 // Hi = Lo << (Shamt-GRLen) 143 144 SDValue Zero = DAG.getConstant(0, DL, VT); 145 SDValue One = DAG.getConstant(1, DL, VT); 146 SDValue MinusGRLen = DAG.getConstant(-(int)Subtarget.getGRLen(), DL, VT); 147 SDValue GRLenMinus1 = DAG.getConstant(Subtarget.getGRLen() - 1, DL, VT); 148 SDValue ShamtMinusGRLen = DAG.getNode(ISD::ADD, DL, VT, Shamt, MinusGRLen); 149 SDValue GRLenMinus1Shamt = DAG.getNode(ISD::XOR, DL, VT, Shamt, GRLenMinus1); 150 151 SDValue LoTrue = DAG.getNode(ISD::SHL, DL, VT, Lo, Shamt); 152 SDValue ShiftRight1Lo = DAG.getNode(ISD::SRL, DL, VT, Lo, One); 153 SDValue ShiftRightLo = 154 DAG.getNode(ISD::SRL, DL, VT, ShiftRight1Lo, GRLenMinus1Shamt); 155 SDValue ShiftLeftHi = DAG.getNode(ISD::SHL, DL, VT, Hi, Shamt); 156 SDValue HiTrue = DAG.getNode(ISD::OR, DL, VT, ShiftLeftHi, ShiftRightLo); 157 SDValue HiFalse = DAG.getNode(ISD::SHL, DL, VT, Lo, ShamtMinusGRLen); 158 159 SDValue CC = DAG.getSetCC(DL, VT, ShamtMinusGRLen, Zero, ISD::SETLT); 160 161 Lo = DAG.getNode(ISD::SELECT, DL, VT, CC, LoTrue, Zero); 162 Hi = DAG.getNode(ISD::SELECT, DL, VT, CC, HiTrue, HiFalse); 163 164 SDValue Parts[2] = {Lo, Hi}; 165 return DAG.getMergeValues(Parts, DL); 166 } 167 168 SDValue LoongArchTargetLowering::lowerShiftRightParts(SDValue Op, 169 SelectionDAG &DAG, 170 bool IsSRA) const { 171 SDLoc DL(Op); 172 SDValue Lo = Op.getOperand(0); 173 SDValue Hi = Op.getOperand(1); 174 SDValue Shamt = Op.getOperand(2); 175 EVT VT = Lo.getValueType(); 176 177 // SRA expansion: 178 // if Shamt-GRLen < 0: // Shamt < GRLen 179 // Lo = (Lo >>u Shamt) | ((Hi << 1) << (ShAmt ^ GRLen-1)) 180 // Hi = Hi >>s Shamt 181 // else: 182 // Lo = Hi >>s (Shamt-GRLen); 183 // Hi = Hi >>s (GRLen-1) 184 // 185 // SRL expansion: 186 // if Shamt-GRLen < 0: // Shamt < GRLen 187 // Lo = (Lo >>u Shamt) | ((Hi << 1) << (ShAmt ^ GRLen-1)) 188 // Hi = Hi >>u Shamt 189 // else: 190 // Lo = Hi >>u (Shamt-GRLen); 191 // Hi = 0; 192 193 unsigned ShiftRightOp = IsSRA ? ISD::SRA : ISD::SRL; 194 195 SDValue Zero = DAG.getConstant(0, DL, VT); 196 SDValue One = DAG.getConstant(1, DL, VT); 197 SDValue MinusGRLen = DAG.getConstant(-(int)Subtarget.getGRLen(), DL, VT); 198 SDValue GRLenMinus1 = DAG.getConstant(Subtarget.getGRLen() - 1, DL, VT); 199 SDValue ShamtMinusGRLen = DAG.getNode(ISD::ADD, DL, VT, Shamt, MinusGRLen); 200 SDValue GRLenMinus1Shamt = DAG.getNode(ISD::XOR, DL, VT, Shamt, GRLenMinus1); 201 202 SDValue ShiftRightLo = DAG.getNode(ISD::SRL, DL, VT, Lo, Shamt); 203 SDValue ShiftLeftHi1 = DAG.getNode(ISD::SHL, DL, VT, Hi, One); 204 SDValue ShiftLeftHi = 205 DAG.getNode(ISD::SHL, DL, VT, ShiftLeftHi1, GRLenMinus1Shamt); 206 SDValue LoTrue = DAG.getNode(ISD::OR, DL, VT, ShiftRightLo, ShiftLeftHi); 207 SDValue HiTrue = DAG.getNode(ShiftRightOp, DL, VT, Hi, Shamt); 208 SDValue LoFalse = DAG.getNode(ShiftRightOp, DL, VT, Hi, ShamtMinusGRLen); 209 SDValue HiFalse = 210 IsSRA ? DAG.getNode(ISD::SRA, DL, VT, Hi, GRLenMinus1) : Zero; 211 212 SDValue CC = DAG.getSetCC(DL, VT, ShamtMinusGRLen, Zero, ISD::SETLT); 213 214 Lo = DAG.getNode(ISD::SELECT, DL, VT, CC, LoTrue, LoFalse); 215 Hi = DAG.getNode(ISD::SELECT, DL, VT, CC, HiTrue, HiFalse); 216 217 SDValue Parts[2] = {Lo, Hi}; 218 return DAG.getMergeValues(Parts, DL); 219 } 220 221 // Returns the opcode of the target-specific SDNode that implements the 32-bit 222 // form of the given Opcode. 223 static LoongArchISD::NodeType getLoongArchWOpcode(unsigned Opcode) { 224 switch (Opcode) { 225 default: 226 llvm_unreachable("Unexpected opcode"); 227 case ISD::SHL: 228 return LoongArchISD::SLL_W; 229 case ISD::SRA: 230 return LoongArchISD::SRA_W; 231 case ISD::SRL: 232 return LoongArchISD::SRL_W; 233 } 234 } 235 236 // Converts the given i8/i16/i32 operation to a target-specific SelectionDAG 237 // node. Because i8/i16/i32 isn't a legal type for LA64, these operations would 238 // otherwise be promoted to i64, making it difficult to select the 239 // SLL_W/.../*W later one because the fact the operation was originally of 240 // type i8/i16/i32 is lost. 241 static SDValue customLegalizeToWOp(SDNode *N, SelectionDAG &DAG, 242 unsigned ExtOpc = ISD::ANY_EXTEND) { 243 SDLoc DL(N); 244 LoongArchISD::NodeType WOpcode = getLoongArchWOpcode(N->getOpcode()); 245 SDValue NewOp0 = DAG.getNode(ExtOpc, DL, MVT::i64, N->getOperand(0)); 246 SDValue NewOp1 = DAG.getNode(ExtOpc, DL, MVT::i64, N->getOperand(1)); 247 SDValue NewRes = DAG.getNode(WOpcode, DL, MVT::i64, NewOp0, NewOp1); 248 // ReplaceNodeResults requires we maintain the same type for the return value. 249 return DAG.getNode(ISD::TRUNCATE, DL, N->getValueType(0), NewRes); 250 } 251 252 void LoongArchTargetLowering::ReplaceNodeResults( 253 SDNode *N, SmallVectorImpl<SDValue> &Results, SelectionDAG &DAG) const { 254 SDLoc DL(N); 255 switch (N->getOpcode()) { 256 default: 257 llvm_unreachable("Don't know how to legalize this operation"); 258 case ISD::SHL: 259 case ISD::SRA: 260 case ISD::SRL: 261 assert(N->getValueType(0) == MVT::i32 && Subtarget.is64Bit() && 262 "Unexpected custom legalisation"); 263 if (N->getOperand(1).getOpcode() != ISD::Constant) { 264 Results.push_back(customLegalizeToWOp(N, DAG)); 265 break; 266 } 267 break; 268 } 269 } 270 271 static SDValue performANDCombine(SDNode *N, SelectionDAG &DAG, 272 TargetLowering::DAGCombinerInfo &DCI, 273 const LoongArchSubtarget &Subtarget) { 274 if (DCI.isBeforeLegalizeOps()) 275 return SDValue(); 276 277 SDValue FirstOperand = N->getOperand(0); 278 SDValue SecondOperand = N->getOperand(1); 279 unsigned FirstOperandOpc = FirstOperand.getOpcode(); 280 EVT ValTy = N->getValueType(0); 281 SDLoc DL(N); 282 uint64_t lsb, msb; 283 unsigned SMIdx, SMLen; 284 ConstantSDNode *CN; 285 SDValue NewOperand; 286 MVT GRLenVT = Subtarget.getGRLenVT(); 287 288 // Op's second operand must be a shifted mask. 289 if (!(CN = dyn_cast<ConstantSDNode>(SecondOperand)) || 290 !isShiftedMask_64(CN->getZExtValue(), SMIdx, SMLen)) 291 return SDValue(); 292 293 if (FirstOperandOpc == ISD::SRA || FirstOperandOpc == ISD::SRL) { 294 // Pattern match BSTRPICK. 295 // $dst = and ((sra or srl) $src , lsb), (2**len - 1) 296 // => BSTRPICK $dst, $src, msb, lsb 297 // where msb = lsb + len - 1 298 299 // The second operand of the shift must be an immediate. 300 if (!(CN = dyn_cast<ConstantSDNode>(FirstOperand.getOperand(1)))) 301 return SDValue(); 302 303 lsb = CN->getZExtValue(); 304 305 // Return if the shifted mask does not start at bit 0 or the sum of its 306 // length and lsb exceeds the word's size. 307 if (SMIdx != 0 || lsb + SMLen > ValTy.getSizeInBits()) 308 return SDValue(); 309 310 NewOperand = FirstOperand.getOperand(0); 311 } else { 312 // Pattern match BSTRPICK. 313 // $dst = and $src, (2**len- 1) , if len > 12 314 // => BSTRPICK $dst, $src, msb, lsb 315 // where lsb = 0 and msb = len - 1 316 317 // If the mask is <= 0xfff, andi can be used instead. 318 if (CN->getZExtValue() <= 0xfff) 319 return SDValue(); 320 321 // Return if the mask doesn't start at position 0. 322 if (SMIdx) 323 return SDValue(); 324 325 lsb = 0; 326 NewOperand = FirstOperand; 327 } 328 msb = lsb + SMLen - 1; 329 return DAG.getNode(LoongArchISD::BSTRPICK, DL, ValTy, NewOperand, 330 DAG.getConstant(msb, DL, GRLenVT), 331 DAG.getConstant(lsb, DL, GRLenVT)); 332 } 333 334 static SDValue performSRLCombine(SDNode *N, SelectionDAG &DAG, 335 TargetLowering::DAGCombinerInfo &DCI, 336 const LoongArchSubtarget &Subtarget) { 337 if (DCI.isBeforeLegalizeOps()) 338 return SDValue(); 339 340 // $dst = srl (and $src, Mask), Shamt 341 // => 342 // BSTRPICK $dst, $src, MaskIdx+MaskLen-1, Shamt 343 // when Mask is a shifted mask, and MaskIdx <= Shamt <= MaskIdx+MaskLen-1 344 // 345 346 SDValue FirstOperand = N->getOperand(0); 347 ConstantSDNode *CN; 348 EVT ValTy = N->getValueType(0); 349 SDLoc DL(N); 350 MVT GRLenVT = Subtarget.getGRLenVT(); 351 unsigned MaskIdx, MaskLen; 352 uint64_t Shamt; 353 354 // The first operand must be an AND and the second operand of the AND must be 355 // a shifted mask. 356 if (FirstOperand.getOpcode() != ISD::AND || 357 !(CN = dyn_cast<ConstantSDNode>(FirstOperand.getOperand(1))) || 358 !isShiftedMask_64(CN->getZExtValue(), MaskIdx, MaskLen)) 359 return SDValue(); 360 361 // The second operand (shift amount) must be an immediate. 362 if (!(CN = dyn_cast<ConstantSDNode>(N->getOperand(1)))) 363 return SDValue(); 364 365 Shamt = CN->getZExtValue(); 366 if (MaskIdx <= Shamt && Shamt <= MaskIdx + MaskLen - 1) 367 return DAG.getNode(LoongArchISD::BSTRPICK, DL, ValTy, 368 FirstOperand->getOperand(0), 369 DAG.getConstant(MaskIdx + MaskLen - 1, DL, GRLenVT), 370 DAG.getConstant(Shamt, DL, GRLenVT)); 371 372 return SDValue(); 373 } 374 375 SDValue LoongArchTargetLowering::PerformDAGCombine(SDNode *N, 376 DAGCombinerInfo &DCI) const { 377 SelectionDAG &DAG = DCI.DAG; 378 switch (N->getOpcode()) { 379 default: 380 break; 381 case ISD::AND: 382 return performANDCombine(N, DAG, DCI, Subtarget); 383 case ISD::SRL: 384 return performSRLCombine(N, DAG, DCI, Subtarget); 385 } 386 return SDValue(); 387 } 388 389 const char *LoongArchTargetLowering::getTargetNodeName(unsigned Opcode) const { 390 switch ((LoongArchISD::NodeType)Opcode) { 391 case LoongArchISD::FIRST_NUMBER: 392 break; 393 394 #define NODE_NAME_CASE(node) \ 395 case LoongArchISD::node: \ 396 return "LoongArchISD::" #node; 397 398 // TODO: Add more target-dependent nodes later. 399 NODE_NAME_CASE(CALL) 400 NODE_NAME_CASE(RET) 401 NODE_NAME_CASE(SLL_W) 402 NODE_NAME_CASE(SRA_W) 403 NODE_NAME_CASE(SRL_W) 404 NODE_NAME_CASE(BSTRPICK) 405 } 406 #undef NODE_NAME_CASE 407 return nullptr; 408 } 409 410 //===----------------------------------------------------------------------===// 411 // Calling Convention Implementation 412 //===----------------------------------------------------------------------===// 413 // FIXME: Now, we only support CallingConv::C with fixed arguments which are 414 // passed with integer or floating-point registers. 415 const MCPhysReg ArgGPRs[] = {LoongArch::R4, LoongArch::R5, LoongArch::R6, 416 LoongArch::R7, LoongArch::R8, LoongArch::R9, 417 LoongArch::R10, LoongArch::R11}; 418 const MCPhysReg ArgFPR32s[] = {LoongArch::F0, LoongArch::F1, LoongArch::F2, 419 LoongArch::F3, LoongArch::F4, LoongArch::F5, 420 LoongArch::F6, LoongArch::F7}; 421 const MCPhysReg ArgFPR64s[] = { 422 LoongArch::F0_64, LoongArch::F1_64, LoongArch::F2_64, LoongArch::F3_64, 423 LoongArch::F4_64, LoongArch::F5_64, LoongArch::F6_64, LoongArch::F7_64}; 424 425 // Implements the LoongArch calling convention. Returns true upon failure. 426 static bool CC_LoongArch(unsigned ValNo, MVT ValVT, 427 CCValAssign::LocInfo LocInfo, CCState &State) { 428 // Allocate to a register if possible. 429 Register Reg; 430 431 if (ValVT == MVT::f32) 432 Reg = State.AllocateReg(ArgFPR32s); 433 else if (ValVT == MVT::f64) 434 Reg = State.AllocateReg(ArgFPR64s); 435 else 436 Reg = State.AllocateReg(ArgGPRs); 437 if (Reg) { 438 State.addLoc(CCValAssign::getReg(ValNo, ValVT, Reg, ValVT, LocInfo)); 439 return false; 440 } 441 442 // TODO: Handle arguments passed without register. 443 return true; 444 } 445 446 void LoongArchTargetLowering::analyzeInputArgs( 447 CCState &CCInfo, const SmallVectorImpl<ISD::InputArg> &Ins, 448 LoongArchCCAssignFn Fn) const { 449 for (unsigned i = 0, e = Ins.size(); i != e; ++i) { 450 MVT ArgVT = Ins[i].VT; 451 452 if (Fn(i, ArgVT, CCValAssign::Full, CCInfo)) { 453 LLVM_DEBUG(dbgs() << "InputArg #" << i << " has unhandled type " 454 << EVT(ArgVT).getEVTString() << '\n'); 455 llvm_unreachable(""); 456 } 457 } 458 } 459 460 void LoongArchTargetLowering::analyzeOutputArgs( 461 CCState &CCInfo, const SmallVectorImpl<ISD::OutputArg> &Outs, 462 LoongArchCCAssignFn Fn) const { 463 for (unsigned i = 0, e = Outs.size(); i != e; ++i) { 464 MVT ArgVT = Outs[i].VT; 465 466 if (Fn(i, ArgVT, CCValAssign::Full, CCInfo)) { 467 LLVM_DEBUG(dbgs() << "OutputArg #" << i << " has unhandled type " 468 << EVT(ArgVT).getEVTString() << "\n"); 469 llvm_unreachable(""); 470 } 471 } 472 } 473 474 static SDValue unpackFromRegLoc(SelectionDAG &DAG, SDValue Chain, 475 const CCValAssign &VA, const SDLoc &DL, 476 const LoongArchTargetLowering &TLI) { 477 MachineFunction &MF = DAG.getMachineFunction(); 478 MachineRegisterInfo &RegInfo = MF.getRegInfo(); 479 EVT LocVT = VA.getLocVT(); 480 const TargetRegisterClass *RC = TLI.getRegClassFor(LocVT.getSimpleVT()); 481 Register VReg = RegInfo.createVirtualRegister(RC); 482 RegInfo.addLiveIn(VA.getLocReg(), VReg); 483 484 return DAG.getCopyFromReg(Chain, DL, VReg, LocVT); 485 } 486 487 // Transform physical registers into virtual registers. 488 SDValue LoongArchTargetLowering::LowerFormalArguments( 489 SDValue Chain, CallingConv::ID CallConv, bool IsVarArg, 490 const SmallVectorImpl<ISD::InputArg> &Ins, const SDLoc &DL, 491 SelectionDAG &DAG, SmallVectorImpl<SDValue> &InVals) const { 492 493 MachineFunction &MF = DAG.getMachineFunction(); 494 495 switch (CallConv) { 496 default: 497 llvm_unreachable("Unsupported calling convention"); 498 case CallingConv::C: 499 break; 500 } 501 502 // Assign locations to all of the incoming arguments. 503 SmallVector<CCValAssign> ArgLocs; 504 CCState CCInfo(CallConv, IsVarArg, MF, ArgLocs, *DAG.getContext()); 505 506 analyzeInputArgs(CCInfo, Ins, CC_LoongArch); 507 508 for (unsigned i = 0, e = ArgLocs.size(); i != e; ++i) 509 InVals.push_back(unpackFromRegLoc(DAG, Chain, ArgLocs[i], DL, *this)); 510 511 return Chain; 512 } 513 514 // Lower a call to a callseq_start + CALL + callseq_end chain, and add input 515 // and output parameter nodes. 516 SDValue 517 LoongArchTargetLowering::LowerCall(CallLoweringInfo &CLI, 518 SmallVectorImpl<SDValue> &InVals) const { 519 SelectionDAG &DAG = CLI.DAG; 520 SDLoc &DL = CLI.DL; 521 SmallVectorImpl<ISD::OutputArg> &Outs = CLI.Outs; 522 SmallVectorImpl<SDValue> &OutVals = CLI.OutVals; 523 SmallVectorImpl<ISD::InputArg> &Ins = CLI.Ins; 524 SDValue Chain = CLI.Chain; 525 SDValue Callee = CLI.Callee; 526 CallingConv::ID CallConv = CLI.CallConv; 527 bool IsVarArg = CLI.IsVarArg; 528 EVT PtrVT = getPointerTy(DAG.getDataLayout()); 529 CLI.IsTailCall = false; 530 531 if (IsVarArg) 532 report_fatal_error("LowerCall with varargs not implemented"); 533 534 MachineFunction &MF = DAG.getMachineFunction(); 535 536 // Analyze the operands of the call, assigning locations to each operand. 537 SmallVector<CCValAssign> ArgLocs; 538 CCState ArgCCInfo(CallConv, IsVarArg, MF, ArgLocs, *DAG.getContext()); 539 540 analyzeOutputArgs(ArgCCInfo, Outs, CC_LoongArch); 541 542 // Get a count of how many bytes are to be pushed on the stack. 543 unsigned NumBytes = ArgCCInfo.getNextStackOffset(); 544 545 for (auto &Arg : Outs) { 546 if (!Arg.Flags.isByVal()) 547 continue; 548 report_fatal_error("Passing arguments byval not implemented"); 549 } 550 551 Chain = DAG.getCALLSEQ_START(Chain, NumBytes, 0, CLI.DL); 552 553 // Copy argument values to their designated locations. 554 SmallVector<std::pair<Register, SDValue>> RegsToPass; 555 for (unsigned i = 0, e = ArgLocs.size(); i != e; ++i) { 556 CCValAssign &VA = ArgLocs[i]; 557 SDValue ArgValue = OutVals[i]; 558 559 // Promote the value if needed. 560 // For now, only handle fully promoted arguments. 561 if (VA.getLocInfo() != CCValAssign::Full) 562 report_fatal_error("Unknown loc info"); 563 564 if (VA.isRegLoc()) { 565 // Queue up the argument copies and emit them at the end. 566 RegsToPass.push_back(std::make_pair(VA.getLocReg(), ArgValue)); 567 } else { 568 report_fatal_error("Passing arguments via the stack not implemented"); 569 } 570 } 571 572 SDValue Glue; 573 574 // Build a sequence of copy-to-reg nodes, chained and glued together. 575 for (auto &Reg : RegsToPass) { 576 Chain = DAG.getCopyToReg(Chain, DL, Reg.first, Reg.second, Glue); 577 Glue = Chain.getValue(1); 578 } 579 580 // If the callee is a GlobalAddress/ExternalSymbol node, turn it into a 581 // TargetGlobalAddress/TargetExternalSymbol node so that legalize won't 582 // split it and then direct call can be matched by PseudoCALL. 583 // FIXME: Add target flags for relocation. 584 if (GlobalAddressSDNode *S = dyn_cast<GlobalAddressSDNode>(Callee)) 585 Callee = DAG.getTargetGlobalAddress(S->getGlobal(), DL, PtrVT); 586 else if (ExternalSymbolSDNode *S = dyn_cast<ExternalSymbolSDNode>(Callee)) 587 Callee = DAG.getTargetExternalSymbol(S->getSymbol(), PtrVT); 588 589 // The first call operand is the chain and the second is the target address. 590 SmallVector<SDValue> Ops; 591 Ops.push_back(Chain); 592 Ops.push_back(Callee); 593 594 // Add argument registers to the end of the list so that they are 595 // known live into the call. 596 for (auto &Reg : RegsToPass) 597 Ops.push_back(DAG.getRegister(Reg.first, Reg.second.getValueType())); 598 599 // Add a register mask operand representing the call-preserved registers. 600 const TargetRegisterInfo *TRI = Subtarget.getRegisterInfo(); 601 const uint32_t *Mask = TRI->getCallPreservedMask(MF, CallConv); 602 assert(Mask && "Missing call preserved mask for calling convention"); 603 Ops.push_back(DAG.getRegisterMask(Mask)); 604 605 // Glue the call to the argument copies, if any. 606 if (Glue.getNode()) 607 Ops.push_back(Glue); 608 609 // Emit the call. 610 SDVTList NodeTys = DAG.getVTList(MVT::Other, MVT::Glue); 611 612 Chain = DAG.getNode(LoongArchISD::CALL, DL, NodeTys, Ops); 613 DAG.addNoMergeSiteInfo(Chain.getNode(), CLI.NoMerge); 614 Glue = Chain.getValue(1); 615 616 // Mark the end of the call, which is glued to the call itself. 617 Chain = DAG.getCALLSEQ_END(Chain, DAG.getConstant(NumBytes, DL, PtrVT, true), 618 DAG.getConstant(0, DL, PtrVT, true), Glue, DL); 619 Glue = Chain.getValue(1); 620 621 // Assign locations to each value returned by this call. 622 SmallVector<CCValAssign> RVLocs; 623 CCState RetCCInfo(CallConv, IsVarArg, MF, RVLocs, *DAG.getContext()); 624 analyzeInputArgs(RetCCInfo, Ins, CC_LoongArch); 625 626 // Copy all of the result registers out of their specified physreg. 627 for (auto &VA : RVLocs) { 628 // Copy the value out. 629 SDValue RetValue = 630 DAG.getCopyFromReg(Chain, DL, VA.getLocReg(), VA.getLocVT(), Glue); 631 Chain = RetValue.getValue(1); 632 Glue = RetValue.getValue(2); 633 634 InVals.push_back(Chain.getValue(0)); 635 } 636 637 return Chain; 638 } 639 640 bool LoongArchTargetLowering::CanLowerReturn( 641 CallingConv::ID CallConv, MachineFunction &MF, bool IsVarArg, 642 const SmallVectorImpl<ISD::OutputArg> &Outs, LLVMContext &Context) const { 643 // Any return value split in to more than two values can't be returned 644 // directly. 645 return Outs.size() <= 2; 646 } 647 648 SDValue LoongArchTargetLowering::LowerReturn( 649 SDValue Chain, CallingConv::ID CallConv, bool IsVarArg, 650 const SmallVectorImpl<ISD::OutputArg> &Outs, 651 const SmallVectorImpl<SDValue> &OutVals, const SDLoc &DL, 652 SelectionDAG &DAG) const { 653 // Stores the assignment of the return value to a location. 654 SmallVector<CCValAssign> RVLocs; 655 656 // Info about the registers and stack slot. 657 CCState CCInfo(CallConv, IsVarArg, DAG.getMachineFunction(), RVLocs, 658 *DAG.getContext()); 659 660 analyzeOutputArgs(CCInfo, Outs, CC_LoongArch); 661 662 SDValue Glue; 663 SmallVector<SDValue, 4> RetOps(1, Chain); 664 665 // Copy the result values into the output registers. 666 for (unsigned i = 0, e = RVLocs.size(); i < e; ++i) { 667 CCValAssign &VA = RVLocs[i]; 668 assert(VA.isRegLoc() && "Can only return in registers!"); 669 670 // Handle a 'normal' return. 671 Chain = DAG.getCopyToReg(Chain, DL, VA.getLocReg(), OutVals[i], Glue); 672 673 // Guarantee that all emitted copies are stuck together. 674 Glue = Chain.getValue(1); 675 RetOps.push_back(DAG.getRegister(VA.getLocReg(), VA.getLocVT())); 676 } 677 678 RetOps[0] = Chain; // Update chain. 679 680 // Add the glue node if we have it. 681 if (Glue.getNode()) 682 RetOps.push_back(Glue); 683 684 return DAG.getNode(LoongArchISD::RET, DL, MVT::Other, RetOps); 685 } 686