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 "llvm/ADT/Statistic.h" 21 #include "llvm/CodeGen/ISDOpcodes.h" 22 #include "llvm/Support/Debug.h" 23 24 using namespace llvm; 25 26 #define DEBUG_TYPE "loongarch-isel-lowering" 27 28 LoongArchTargetLowering::LoongArchTargetLowering(const TargetMachine &TM, 29 const LoongArchSubtarget &STI) 30 : TargetLowering(TM), Subtarget(STI) { 31 32 MVT GRLenVT = Subtarget.getGRLenVT(); 33 // Set up the register classes. 34 addRegisterClass(GRLenVT, &LoongArch::GPRRegClass); 35 if (Subtarget.hasBasicF()) 36 addRegisterClass(MVT::f32, &LoongArch::FPR32RegClass); 37 if (Subtarget.hasBasicD()) 38 addRegisterClass(MVT::f64, &LoongArch::FPR64RegClass); 39 40 // TODO: add necessary setOperationAction calls later. 41 setOperationAction(ISD::SHL_PARTS, GRLenVT, Custom); 42 setOperationAction(ISD::SRA_PARTS, GRLenVT, Custom); 43 setOperationAction(ISD::SRL_PARTS, GRLenVT, Custom); 44 45 if (Subtarget.is64Bit()) { 46 setOperationAction(ISD::SHL, MVT::i32, Custom); 47 setOperationAction(ISD::SRA, MVT::i32, Custom); 48 setOperationAction(ISD::SRL, MVT::i32, Custom); 49 } 50 51 static const ISD::CondCode FPCCToExpand[] = {ISD::SETOGT, ISD::SETOGE, 52 ISD::SETUGT, ISD::SETUGE}; 53 54 if (Subtarget.hasBasicF()) { 55 setCondCodeAction(FPCCToExpand, MVT::f32, Expand); 56 setOperationAction(ISD::SELECT_CC, MVT::f32, Expand); 57 } 58 if (Subtarget.hasBasicD()) { 59 setCondCodeAction(FPCCToExpand, MVT::f64, Expand); 60 setOperationAction(ISD::SELECT_CC, MVT::f64, Expand); 61 } 62 63 setOperationAction(ISD::SELECT_CC, GRLenVT, Expand); 64 setOperationAction(ISD::SIGN_EXTEND_INREG, MVT::i1, Expand); 65 66 // Compute derived properties from the register classes. 67 computeRegisterProperties(STI.getRegisterInfo()); 68 69 setStackPointerRegisterToSaveRestore(LoongArch::R3); 70 71 setBooleanContents(ZeroOrOneBooleanContent); 72 73 // Function alignments. 74 const Align FunctionAlignment(4); 75 setMinFunctionAlignment(FunctionAlignment); 76 77 setTargetDAGCombine(ISD::AND); 78 setTargetDAGCombine(ISD::SRL); 79 } 80 81 SDValue LoongArchTargetLowering::LowerOperation(SDValue Op, 82 SelectionDAG &DAG) const { 83 switch (Op.getOpcode()) { 84 default: 85 report_fatal_error("unimplemented operand"); 86 case ISD::SHL_PARTS: 87 return lowerShiftLeftParts(Op, DAG); 88 case ISD::SRA_PARTS: 89 return lowerShiftRightParts(Op, DAG, true); 90 case ISD::SRL_PARTS: 91 return lowerShiftRightParts(Op, DAG, false); 92 case ISD::SHL: 93 case ISD::SRA: 94 case ISD::SRL: 95 // This can be called for an i32 shift amount that needs to be promoted. 96 assert(Op.getOperand(1).getValueType() == MVT::i32 && Subtarget.is64Bit() && 97 "Unexpected custom legalisation"); 98 return SDValue(); 99 } 100 } 101 102 SDValue LoongArchTargetLowering::lowerShiftLeftParts(SDValue Op, 103 SelectionDAG &DAG) const { 104 SDLoc DL(Op); 105 SDValue Lo = Op.getOperand(0); 106 SDValue Hi = Op.getOperand(1); 107 SDValue Shamt = Op.getOperand(2); 108 EVT VT = Lo.getValueType(); 109 110 // if Shamt-GRLen < 0: // Shamt < GRLen 111 // Lo = Lo << Shamt 112 // Hi = (Hi << Shamt) | ((Lo >>u 1) >>u (GRLen-1 ^ Shamt)) 113 // else: 114 // Lo = 0 115 // Hi = Lo << (Shamt-GRLen) 116 117 SDValue Zero = DAG.getConstant(0, DL, VT); 118 SDValue One = DAG.getConstant(1, DL, VT); 119 SDValue MinusGRLen = DAG.getConstant(-(int)Subtarget.getGRLen(), DL, VT); 120 SDValue GRLenMinus1 = DAG.getConstant(Subtarget.getGRLen() - 1, DL, VT); 121 SDValue ShamtMinusGRLen = DAG.getNode(ISD::ADD, DL, VT, Shamt, MinusGRLen); 122 SDValue GRLenMinus1Shamt = DAG.getNode(ISD::XOR, DL, VT, Shamt, GRLenMinus1); 123 124 SDValue LoTrue = DAG.getNode(ISD::SHL, DL, VT, Lo, Shamt); 125 SDValue ShiftRight1Lo = DAG.getNode(ISD::SRL, DL, VT, Lo, One); 126 SDValue ShiftRightLo = 127 DAG.getNode(ISD::SRL, DL, VT, ShiftRight1Lo, GRLenMinus1Shamt); 128 SDValue ShiftLeftHi = DAG.getNode(ISD::SHL, DL, VT, Hi, Shamt); 129 SDValue HiTrue = DAG.getNode(ISD::OR, DL, VT, ShiftLeftHi, ShiftRightLo); 130 SDValue HiFalse = DAG.getNode(ISD::SHL, DL, VT, Lo, ShamtMinusGRLen); 131 132 SDValue CC = DAG.getSetCC(DL, VT, ShamtMinusGRLen, Zero, ISD::SETLT); 133 134 Lo = DAG.getNode(ISD::SELECT, DL, VT, CC, LoTrue, Zero); 135 Hi = DAG.getNode(ISD::SELECT, DL, VT, CC, HiTrue, HiFalse); 136 137 SDValue Parts[2] = {Lo, Hi}; 138 return DAG.getMergeValues(Parts, DL); 139 } 140 141 SDValue LoongArchTargetLowering::lowerShiftRightParts(SDValue Op, 142 SelectionDAG &DAG, 143 bool IsSRA) const { 144 SDLoc DL(Op); 145 SDValue Lo = Op.getOperand(0); 146 SDValue Hi = Op.getOperand(1); 147 SDValue Shamt = Op.getOperand(2); 148 EVT VT = Lo.getValueType(); 149 150 // SRA expansion: 151 // if Shamt-GRLen < 0: // Shamt < GRLen 152 // Lo = (Lo >>u Shamt) | ((Hi << 1) << (ShAmt ^ GRLen-1)) 153 // Hi = Hi >>s Shamt 154 // else: 155 // Lo = Hi >>s (Shamt-GRLen); 156 // Hi = Hi >>s (GRLen-1) 157 // 158 // SRL expansion: 159 // if Shamt-GRLen < 0: // Shamt < GRLen 160 // Lo = (Lo >>u Shamt) | ((Hi << 1) << (ShAmt ^ GRLen-1)) 161 // Hi = Hi >>u Shamt 162 // else: 163 // Lo = Hi >>u (Shamt-GRLen); 164 // Hi = 0; 165 166 unsigned ShiftRightOp = IsSRA ? ISD::SRA : ISD::SRL; 167 168 SDValue Zero = DAG.getConstant(0, DL, VT); 169 SDValue One = DAG.getConstant(1, DL, VT); 170 SDValue MinusGRLen = DAG.getConstant(-(int)Subtarget.getGRLen(), DL, VT); 171 SDValue GRLenMinus1 = DAG.getConstant(Subtarget.getGRLen() - 1, DL, VT); 172 SDValue ShamtMinusGRLen = DAG.getNode(ISD::ADD, DL, VT, Shamt, MinusGRLen); 173 SDValue GRLenMinus1Shamt = DAG.getNode(ISD::XOR, DL, VT, Shamt, GRLenMinus1); 174 175 SDValue ShiftRightLo = DAG.getNode(ISD::SRL, DL, VT, Lo, Shamt); 176 SDValue ShiftLeftHi1 = DAG.getNode(ISD::SHL, DL, VT, Hi, One); 177 SDValue ShiftLeftHi = 178 DAG.getNode(ISD::SHL, DL, VT, ShiftLeftHi1, GRLenMinus1Shamt); 179 SDValue LoTrue = DAG.getNode(ISD::OR, DL, VT, ShiftRightLo, ShiftLeftHi); 180 SDValue HiTrue = DAG.getNode(ShiftRightOp, DL, VT, Hi, Shamt); 181 SDValue LoFalse = DAG.getNode(ShiftRightOp, DL, VT, Hi, ShamtMinusGRLen); 182 SDValue HiFalse = 183 IsSRA ? DAG.getNode(ISD::SRA, DL, VT, Hi, GRLenMinus1) : Zero; 184 185 SDValue CC = DAG.getSetCC(DL, VT, ShamtMinusGRLen, Zero, ISD::SETLT); 186 187 Lo = DAG.getNode(ISD::SELECT, DL, VT, CC, LoTrue, LoFalse); 188 Hi = DAG.getNode(ISD::SELECT, DL, VT, CC, HiTrue, HiFalse); 189 190 SDValue Parts[2] = {Lo, Hi}; 191 return DAG.getMergeValues(Parts, DL); 192 } 193 194 // Returns the opcode of the target-specific SDNode that implements the 32-bit 195 // form of the given Opcode. 196 static LoongArchISD::NodeType getLoongArchWOpcode(unsigned Opcode) { 197 switch (Opcode) { 198 default: 199 llvm_unreachable("Unexpected opcode"); 200 case ISD::SHL: 201 return LoongArchISD::SLL_W; 202 case ISD::SRA: 203 return LoongArchISD::SRA_W; 204 case ISD::SRL: 205 return LoongArchISD::SRL_W; 206 } 207 } 208 209 // Converts the given i8/i16/i32 operation to a target-specific SelectionDAG 210 // node. Because i8/i16/i32 isn't a legal type for LA64, these operations would 211 // otherwise be promoted to i64, making it difficult to select the 212 // SLL_W/.../*W later one because the fact the operation was originally of 213 // type i8/i16/i32 is lost. 214 static SDValue customLegalizeToWOp(SDNode *N, SelectionDAG &DAG, 215 unsigned ExtOpc = ISD::ANY_EXTEND) { 216 SDLoc DL(N); 217 LoongArchISD::NodeType WOpcode = getLoongArchWOpcode(N->getOpcode()); 218 SDValue NewOp0 = DAG.getNode(ExtOpc, DL, MVT::i64, N->getOperand(0)); 219 SDValue NewOp1 = DAG.getNode(ExtOpc, DL, MVT::i64, N->getOperand(1)); 220 SDValue NewRes = DAG.getNode(WOpcode, DL, MVT::i64, NewOp0, NewOp1); 221 // ReplaceNodeResults requires we maintain the same type for the return value. 222 return DAG.getNode(ISD::TRUNCATE, DL, N->getValueType(0), NewRes); 223 } 224 225 void LoongArchTargetLowering::ReplaceNodeResults( 226 SDNode *N, SmallVectorImpl<SDValue> &Results, SelectionDAG &DAG) const { 227 SDLoc DL(N); 228 switch (N->getOpcode()) { 229 default: 230 llvm_unreachable("Don't know how to legalize this operation"); 231 case ISD::SHL: 232 case ISD::SRA: 233 case ISD::SRL: 234 assert(N->getValueType(0) == MVT::i32 && Subtarget.is64Bit() && 235 "Unexpected custom legalisation"); 236 if (N->getOperand(1).getOpcode() != ISD::Constant) { 237 Results.push_back(customLegalizeToWOp(N, DAG)); 238 break; 239 } 240 break; 241 } 242 } 243 244 static SDValue performANDCombine(SDNode *N, SelectionDAG &DAG, 245 TargetLowering::DAGCombinerInfo &DCI, 246 const LoongArchSubtarget &Subtarget) { 247 if (DCI.isBeforeLegalizeOps()) 248 return SDValue(); 249 250 SDValue FirstOperand = N->getOperand(0); 251 SDValue SecondOperand = N->getOperand(1); 252 unsigned FirstOperandOpc = FirstOperand.getOpcode(); 253 EVT ValTy = N->getValueType(0); 254 SDLoc DL(N); 255 uint64_t lsb, msb; 256 unsigned SMIdx, SMLen; 257 ConstantSDNode *CN; 258 SDValue NewOperand; 259 MVT GRLenVT = Subtarget.getGRLenVT(); 260 261 // Op's second operand must be a shifted mask. 262 if (!(CN = dyn_cast<ConstantSDNode>(SecondOperand)) || 263 !isShiftedMask_64(CN->getZExtValue(), SMIdx, SMLen)) 264 return SDValue(); 265 266 if (FirstOperandOpc == ISD::SRA || FirstOperandOpc == ISD::SRL) { 267 // Pattern match BSTRPICK. 268 // $dst = and ((sra or srl) $src , lsb), (2**len - 1) 269 // => BSTRPICK $dst, $src, msb, lsb 270 // where msb = lsb + len - 1 271 272 // The second operand of the shift must be an immediate. 273 if (!(CN = dyn_cast<ConstantSDNode>(FirstOperand.getOperand(1)))) 274 return SDValue(); 275 276 lsb = CN->getZExtValue(); 277 278 // Return if the shifted mask does not start at bit 0 or the sum of its 279 // length and lsb exceeds the word's size. 280 if (SMIdx != 0 || lsb + SMLen > ValTy.getSizeInBits()) 281 return SDValue(); 282 283 NewOperand = FirstOperand.getOperand(0); 284 } else { 285 // Pattern match BSTRPICK. 286 // $dst = and $src, (2**len- 1) , if len > 12 287 // => BSTRPICK $dst, $src, msb, lsb 288 // where lsb = 0 and msb = len - 1 289 290 // If the mask is <= 0xfff, andi can be used instead. 291 if (CN->getZExtValue() <= 0xfff) 292 return SDValue(); 293 294 // Return if the mask doesn't start at position 0. 295 if (SMIdx) 296 return SDValue(); 297 298 lsb = 0; 299 NewOperand = FirstOperand; 300 } 301 msb = lsb + SMLen - 1; 302 return DAG.getNode(LoongArchISD::BSTRPICK, DL, ValTy, NewOperand, 303 DAG.getConstant(msb, DL, GRLenVT), 304 DAG.getConstant(lsb, DL, GRLenVT)); 305 } 306 307 static SDValue performSRLCombine(SDNode *N, SelectionDAG &DAG, 308 TargetLowering::DAGCombinerInfo &DCI, 309 const LoongArchSubtarget &Subtarget) { 310 if (DCI.isBeforeLegalizeOps()) 311 return SDValue(); 312 313 // $dst = srl (and $src, Mask), Shamt 314 // => 315 // BSTRPICK $dst, $src, MaskIdx+MaskLen-1, Shamt 316 // when Mask is a shifted mask, and MaskIdx <= Shamt <= MaskIdx+MaskLen-1 317 // 318 319 SDValue FirstOperand = N->getOperand(0); 320 ConstantSDNode *CN; 321 EVT ValTy = N->getValueType(0); 322 SDLoc DL(N); 323 MVT GRLenVT = Subtarget.getGRLenVT(); 324 unsigned MaskIdx, MaskLen; 325 uint64_t Shamt; 326 327 // The first operand must be an AND and the second operand of the AND must be 328 // a shifted mask. 329 if (FirstOperand.getOpcode() != ISD::AND || 330 !(CN = dyn_cast<ConstantSDNode>(FirstOperand.getOperand(1))) || 331 !isShiftedMask_64(CN->getZExtValue(), MaskIdx, MaskLen)) 332 return SDValue(); 333 334 // The second operand (shift amount) must be an immediate. 335 if (!(CN = dyn_cast<ConstantSDNode>(N->getOperand(1)))) 336 return SDValue(); 337 338 Shamt = CN->getZExtValue(); 339 if (MaskIdx <= Shamt && Shamt <= MaskIdx + MaskLen - 1) 340 return DAG.getNode(LoongArchISD::BSTRPICK, DL, ValTy, 341 FirstOperand->getOperand(0), 342 DAG.getConstant(MaskIdx + MaskLen - 1, DL, GRLenVT), 343 DAG.getConstant(Shamt, DL, GRLenVT)); 344 345 return SDValue(); 346 } 347 348 SDValue LoongArchTargetLowering::PerformDAGCombine(SDNode *N, 349 DAGCombinerInfo &DCI) const { 350 SelectionDAG &DAG = DCI.DAG; 351 switch (N->getOpcode()) { 352 default: 353 break; 354 case ISD::AND: 355 return performANDCombine(N, DAG, DCI, Subtarget); 356 case ISD::SRL: 357 return performSRLCombine(N, DAG, DCI, Subtarget); 358 } 359 return SDValue(); 360 } 361 362 const char *LoongArchTargetLowering::getTargetNodeName(unsigned Opcode) const { 363 switch ((LoongArchISD::NodeType)Opcode) { 364 case LoongArchISD::FIRST_NUMBER: 365 break; 366 367 #define NODE_NAME_CASE(node) \ 368 case LoongArchISD::node: \ 369 return "LoongArchISD::" #node; 370 371 // TODO: Add more target-dependent nodes later. 372 NODE_NAME_CASE(RET) 373 NODE_NAME_CASE(SLL_W) 374 NODE_NAME_CASE(SRA_W) 375 NODE_NAME_CASE(SRL_W) 376 NODE_NAME_CASE(BSTRPICK) 377 } 378 #undef NODE_NAME_CASE 379 return nullptr; 380 } 381 382 //===----------------------------------------------------------------------===// 383 // Calling Convention Implementation 384 //===----------------------------------------------------------------------===// 385 // FIXME: Now, we only support CallingConv::C with fixed arguments which are 386 // passed with integer or floating-point registers. 387 const MCPhysReg ArgGPRs[] = {LoongArch::R4, LoongArch::R5, LoongArch::R6, 388 LoongArch::R7, LoongArch::R8, LoongArch::R9, 389 LoongArch::R10, LoongArch::R11}; 390 const MCPhysReg ArgFPR32s[] = {LoongArch::F0, LoongArch::F1, LoongArch::F2, 391 LoongArch::F3, LoongArch::F4, LoongArch::F5, 392 LoongArch::F6, LoongArch::F7}; 393 const MCPhysReg ArgFPR64s[] = { 394 LoongArch::F0_64, LoongArch::F1_64, LoongArch::F2_64, LoongArch::F3_64, 395 LoongArch::F4_64, LoongArch::F5_64, LoongArch::F6_64, LoongArch::F7_64}; 396 397 // Implements the LoongArch calling convention. Returns true upon failure. 398 static bool CC_LoongArch(unsigned ValNo, MVT ValVT, 399 CCValAssign::LocInfo LocInfo, CCState &State) { 400 // Allocate to a register if possible. 401 Register Reg; 402 403 if (ValVT == MVT::f32) 404 Reg = State.AllocateReg(ArgFPR32s); 405 else if (ValVT == MVT::f64) 406 Reg = State.AllocateReg(ArgFPR64s); 407 else 408 Reg = State.AllocateReg(ArgGPRs); 409 if (Reg) { 410 State.addLoc(CCValAssign::getReg(ValNo, ValVT, Reg, ValVT, LocInfo)); 411 return false; 412 } 413 414 // TODO: Handle arguments passed without register. 415 return true; 416 } 417 418 void LoongArchTargetLowering::analyzeInputArgs( 419 CCState &CCInfo, const SmallVectorImpl<ISD::InputArg> &Ins, 420 LoongArchCCAssignFn Fn) const { 421 for (unsigned i = 0, e = Ins.size(); i != e; ++i) { 422 MVT ArgVT = Ins[i].VT; 423 424 if (Fn(i, ArgVT, CCValAssign::Full, CCInfo)) { 425 LLVM_DEBUG(dbgs() << "InputArg #" << i << " has unhandled type " 426 << EVT(ArgVT).getEVTString() << '\n'); 427 llvm_unreachable(""); 428 } 429 } 430 } 431 432 void LoongArchTargetLowering::analyzeOutputArgs( 433 CCState &CCInfo, const SmallVectorImpl<ISD::OutputArg> &Outs, 434 LoongArchCCAssignFn Fn) const { 435 for (unsigned i = 0, e = Outs.size(); i != e; ++i) { 436 MVT ArgVT = Outs[i].VT; 437 438 if (Fn(i, ArgVT, CCValAssign::Full, CCInfo)) { 439 LLVM_DEBUG(dbgs() << "OutputArg #" << i << " has unhandled type " 440 << EVT(ArgVT).getEVTString() << "\n"); 441 llvm_unreachable(""); 442 } 443 } 444 } 445 446 static SDValue unpackFromRegLoc(SelectionDAG &DAG, SDValue Chain, 447 const CCValAssign &VA, const SDLoc &DL, 448 const LoongArchTargetLowering &TLI) { 449 MachineFunction &MF = DAG.getMachineFunction(); 450 MachineRegisterInfo &RegInfo = MF.getRegInfo(); 451 EVT LocVT = VA.getLocVT(); 452 const TargetRegisterClass *RC = TLI.getRegClassFor(LocVT.getSimpleVT()); 453 Register VReg = RegInfo.createVirtualRegister(RC); 454 RegInfo.addLiveIn(VA.getLocReg(), VReg); 455 456 return DAG.getCopyFromReg(Chain, DL, VReg, LocVT); 457 } 458 459 // Transform physical registers into virtual registers. 460 SDValue LoongArchTargetLowering::LowerFormalArguments( 461 SDValue Chain, CallingConv::ID CallConv, bool IsVarArg, 462 const SmallVectorImpl<ISD::InputArg> &Ins, const SDLoc &DL, 463 SelectionDAG &DAG, SmallVectorImpl<SDValue> &InVals) const { 464 465 MachineFunction &MF = DAG.getMachineFunction(); 466 467 switch (CallConv) { 468 default: 469 llvm_unreachable("Unsupported calling convention"); 470 case CallingConv::C: 471 break; 472 } 473 474 // Assign locations to all of the incoming arguments. 475 SmallVector<CCValAssign> ArgLocs; 476 CCState CCInfo(CallConv, IsVarArg, MF, ArgLocs, *DAG.getContext()); 477 478 analyzeInputArgs(CCInfo, Ins, CC_LoongArch); 479 480 for (unsigned i = 0, e = ArgLocs.size(); i != e; ++i) 481 InVals.push_back(unpackFromRegLoc(DAG, Chain, ArgLocs[i], DL, *this)); 482 483 return Chain; 484 } 485 486 bool LoongArchTargetLowering::CanLowerReturn( 487 CallingConv::ID CallConv, MachineFunction &MF, bool IsVarArg, 488 const SmallVectorImpl<ISD::OutputArg> &Outs, LLVMContext &Context) const { 489 // Any return value split in to more than two values can't be returned 490 // directly. 491 return Outs.size() <= 2; 492 } 493 494 SDValue LoongArchTargetLowering::LowerReturn( 495 SDValue Chain, CallingConv::ID CallConv, bool IsVarArg, 496 const SmallVectorImpl<ISD::OutputArg> &Outs, 497 const SmallVectorImpl<SDValue> &OutVals, const SDLoc &DL, 498 SelectionDAG &DAG) const { 499 // Stores the assignment of the return value to a location. 500 SmallVector<CCValAssign> RVLocs; 501 502 // Info about the registers and stack slot. 503 CCState CCInfo(CallConv, IsVarArg, DAG.getMachineFunction(), RVLocs, 504 *DAG.getContext()); 505 506 analyzeOutputArgs(CCInfo, Outs, CC_LoongArch); 507 508 SDValue Glue; 509 SmallVector<SDValue, 4> RetOps(1, Chain); 510 511 // Copy the result values into the output registers. 512 for (unsigned i = 0, e = RVLocs.size(); i < e; ++i) { 513 CCValAssign &VA = RVLocs[i]; 514 assert(VA.isRegLoc() && "Can only return in registers!"); 515 516 // Handle a 'normal' return. 517 Chain = DAG.getCopyToReg(Chain, DL, VA.getLocReg(), OutVals[i], Glue); 518 519 // Guarantee that all emitted copies are stuck together. 520 Glue = Chain.getValue(1); 521 RetOps.push_back(DAG.getRegister(VA.getLocReg(), VA.getLocVT())); 522 } 523 524 RetOps[0] = Chain; // Update chain. 525 526 // Add the glue node if we have it. 527 if (Glue.getNode()) 528 RetOps.push_back(Glue); 529 530 return DAG.getNode(LoongArchISD::RET, DL, MVT::Other, RetOps); 531 } 532