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