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