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 #include "llvm/Support/KnownBits.h" 25 26 using namespace llvm; 27 28 #define DEBUG_TYPE "loongarch-isel-lowering" 29 30 static cl::opt<bool> ZeroDivCheck( 31 "loongarch-check-zero-division", cl::Hidden, 32 cl::desc("Trap on integer division by zero."), 33 cl::init(false)); 34 35 LoongArchTargetLowering::LoongArchTargetLowering(const TargetMachine &TM, 36 const LoongArchSubtarget &STI) 37 : TargetLowering(TM), Subtarget(STI) { 38 39 MVT GRLenVT = Subtarget.getGRLenVT(); 40 // Set up the register classes. 41 addRegisterClass(GRLenVT, &LoongArch::GPRRegClass); 42 if (Subtarget.hasBasicF()) 43 addRegisterClass(MVT::f32, &LoongArch::FPR32RegClass); 44 if (Subtarget.hasBasicD()) 45 addRegisterClass(MVT::f64, &LoongArch::FPR64RegClass); 46 47 setLoadExtAction({ISD::EXTLOAD, ISD::SEXTLOAD, ISD::ZEXTLOAD}, GRLenVT, 48 MVT::i1, Promote); 49 50 // TODO: add necessary setOperationAction calls later. 51 setOperationAction(ISD::SHL_PARTS, GRLenVT, Custom); 52 setOperationAction(ISD::SRA_PARTS, GRLenVT, Custom); 53 setOperationAction(ISD::SRL_PARTS, GRLenVT, Custom); 54 setOperationAction(ISD::FP_TO_SINT, GRLenVT, Custom); 55 56 setOperationAction({ISD::GlobalAddress, ISD::ConstantPool}, GRLenVT, Custom); 57 58 if (Subtarget.is64Bit()) { 59 setOperationAction(ISD::SHL, MVT::i32, Custom); 60 setOperationAction(ISD::SRA, MVT::i32, Custom); 61 setOperationAction(ISD::SRL, MVT::i32, Custom); 62 setOperationAction(ISD::FP_TO_SINT, MVT::i32, Custom); 63 setOperationAction(ISD::BITCAST, MVT::i32, Custom); 64 if (Subtarget.hasBasicF() && !Subtarget.hasBasicD()) 65 setOperationAction(ISD::FP_TO_UINT, MVT::i32, Custom); 66 } 67 68 static const ISD::CondCode FPCCToExpand[] = {ISD::SETOGT, ISD::SETOGE, 69 ISD::SETUGT, ISD::SETUGE}; 70 71 if (Subtarget.hasBasicF()) { 72 setCondCodeAction(FPCCToExpand, MVT::f32, Expand); 73 setOperationAction(ISD::SELECT_CC, MVT::f32, Expand); 74 } 75 if (Subtarget.hasBasicD()) { 76 setCondCodeAction(FPCCToExpand, MVT::f64, Expand); 77 setOperationAction(ISD::SELECT_CC, MVT::f64, Expand); 78 setLoadExtAction(ISD::EXTLOAD, MVT::f64, MVT::f32, Expand); 79 setLoadExtAction(ISD::EXTLOAD, MVT::f64, MVT::f32, Expand); 80 } 81 82 setOperationAction(ISD::BR_CC, GRLenVT, Expand); 83 setOperationAction(ISD::SELECT_CC, GRLenVT, Expand); 84 setOperationAction(ISD::SIGN_EXTEND_INREG, MVT::i1, Expand); 85 setOperationAction({ISD::SMUL_LOHI, ISD::UMUL_LOHI}, GRLenVT, Expand); 86 if (!Subtarget.is64Bit()) 87 setLibcallName(RTLIB::MUL_I128, nullptr); 88 89 setOperationAction(ISD::FP_TO_UINT, GRLenVT, Custom); 90 setOperationAction(ISD::UINT_TO_FP, GRLenVT, Custom); 91 92 // Compute derived properties from the register classes. 93 computeRegisterProperties(STI.getRegisterInfo()); 94 95 setStackPointerRegisterToSaveRestore(LoongArch::R3); 96 97 setBooleanContents(ZeroOrOneBooleanContent); 98 99 setMaxAtomicSizeInBitsSupported(Subtarget.getGRLen()); 100 101 // Function alignments. 102 const Align FunctionAlignment(4); 103 setMinFunctionAlignment(FunctionAlignment); 104 105 setTargetDAGCombine(ISD::AND); 106 setTargetDAGCombine(ISD::OR); 107 setTargetDAGCombine(ISD::SRL); 108 } 109 110 SDValue LoongArchTargetLowering::LowerOperation(SDValue Op, 111 SelectionDAG &DAG) const { 112 switch (Op.getOpcode()) { 113 default: 114 report_fatal_error("unimplemented operand"); 115 case ISD::GlobalAddress: 116 return lowerGlobalAddress(Op, DAG); 117 case ISD::SHL_PARTS: 118 return lowerShiftLeftParts(Op, DAG); 119 case ISD::SRA_PARTS: 120 return lowerShiftRightParts(Op, DAG, true); 121 case ISD::SRL_PARTS: 122 return lowerShiftRightParts(Op, DAG, false); 123 case ISD::SHL: 124 case ISD::SRA: 125 case ISD::SRL: 126 // This can be called for an i32 shift amount that needs to be promoted. 127 assert(Op.getOperand(1).getValueType() == MVT::i32 && Subtarget.is64Bit() && 128 "Unexpected custom legalisation"); 129 return SDValue(); 130 case ISD::ConstantPool: 131 return lowerConstantPool(Op, DAG); 132 case ISD::FP_TO_SINT: 133 return lowerFP_TO_SINT(Op, DAG); 134 case ISD::BITCAST: 135 return lowerBITCAST(Op, DAG); 136 case ISD::FP_TO_UINT: 137 return SDValue(); 138 case ISD::UINT_TO_FP: 139 return lowerUINT_TO_FP(Op, DAG); 140 } 141 } 142 143 SDValue LoongArchTargetLowering::lowerUINT_TO_FP(SDValue Op, 144 SelectionDAG &DAG) const { 145 146 SDLoc DL(Op); 147 auto &TLI = DAG.getTargetLoweringInfo(); 148 SDValue Tmp1, Tmp2; 149 SDValue Op1 = Op.getOperand(0); 150 if (Op1->getOpcode() == ISD::AssertZext || 151 Op1->getOpcode() == ISD::AssertSext) 152 return Op; 153 SDValue Trunc = DAG.getNode(ISD::TRUNCATE, DL, MVT::i32, Op.getOperand(0)); 154 SDValue Res = DAG.getNode(ISD::UINT_TO_FP, DL, MVT::f64, Trunc); 155 SDNode *N = Res.getNode(); 156 TLI.expandUINT_TO_FP(N, Tmp1, Tmp2, DAG); 157 return Tmp1; 158 } 159 160 SDValue LoongArchTargetLowering::lowerBITCAST(SDValue Op, 161 SelectionDAG &DAG) const { 162 163 SDLoc DL(Op); 164 SDValue Op0 = Op.getOperand(0); 165 166 if (Op.getValueType() == MVT::f32 && Op0.getValueType() == MVT::i32 && 167 Subtarget.is64Bit() && Subtarget.hasBasicF()) { 168 SDValue NewOp0 = DAG.getNode(ISD::ANY_EXTEND, DL, MVT::i64, Op0); 169 return DAG.getNode(LoongArchISD::MOVGR2FR_W_LA64, DL, MVT::f32, NewOp0); 170 } 171 return Op; 172 } 173 174 SDValue LoongArchTargetLowering::lowerFP_TO_SINT(SDValue Op, 175 SelectionDAG &DAG) const { 176 177 SDLoc DL(Op); 178 179 if (Op.getValueSizeInBits() > 32 && Subtarget.hasBasicF() && 180 !Subtarget.hasBasicD()) { 181 SDValue Dst = 182 DAG.getNode(LoongArchISD::FTINT, DL, MVT::f32, Op.getOperand(0)); 183 return DAG.getNode(LoongArchISD::MOVFR2GR_S_LA64, DL, MVT::i64, Dst); 184 } 185 186 EVT FPTy = EVT::getFloatingPointVT(Op.getValueSizeInBits()); 187 SDValue Trunc = DAG.getNode(LoongArchISD::FTINT, DL, FPTy, Op.getOperand(0)); 188 return DAG.getNode(ISD::BITCAST, DL, Op.getValueType(), Trunc); 189 } 190 191 SDValue LoongArchTargetLowering::lowerConstantPool(SDValue Op, 192 SelectionDAG &DAG) const { 193 SDLoc DL(Op); 194 EVT Ty = Op.getValueType(); 195 ConstantPoolSDNode *N = cast<ConstantPoolSDNode>(Op); 196 197 // FIXME: Only support PC-relative addressing to access the symbol. 198 // Target flags will be added later. 199 if (!isPositionIndependent()) { 200 SDValue ConstantN = DAG.getTargetConstantPool( 201 N->getConstVal(), Ty, N->getAlign(), N->getOffset()); 202 SDValue AddrHi(DAG.getMachineNode(LoongArch::PCALAU12I, DL, Ty, ConstantN), 203 0); 204 SDValue Addr(DAG.getMachineNode(Subtarget.is64Bit() ? LoongArch::ADDI_D 205 : LoongArch::ADDI_W, 206 DL, Ty, AddrHi, ConstantN), 207 0); 208 return Addr; 209 } 210 report_fatal_error("Unable to lower ConstantPool"); 211 } 212 213 SDValue LoongArchTargetLowering::lowerGlobalAddress(SDValue Op, 214 SelectionDAG &DAG) const { 215 SDLoc DL(Op); 216 EVT Ty = getPointerTy(DAG.getDataLayout()); 217 const GlobalValue *GV = cast<GlobalAddressSDNode>(Op)->getGlobal(); 218 unsigned ADDIOp = Subtarget.is64Bit() ? LoongArch::ADDI_D : LoongArch::ADDI_W; 219 220 // FIXME: Only support PC-relative addressing to access the symbol. 221 // TODO: Add target flags. 222 if (!isPositionIndependent()) { 223 SDValue GA = DAG.getTargetGlobalAddress(GV, DL, Ty); 224 SDValue AddrHi(DAG.getMachineNode(LoongArch::PCALAU12I, DL, Ty, GA), 0); 225 SDValue Addr(DAG.getMachineNode(ADDIOp, DL, Ty, AddrHi, GA), 0); 226 return Addr; 227 } 228 report_fatal_error("Unable to lowerGlobalAddress"); 229 } 230 231 SDValue LoongArchTargetLowering::lowerShiftLeftParts(SDValue Op, 232 SelectionDAG &DAG) const { 233 SDLoc DL(Op); 234 SDValue Lo = Op.getOperand(0); 235 SDValue Hi = Op.getOperand(1); 236 SDValue Shamt = Op.getOperand(2); 237 EVT VT = Lo.getValueType(); 238 239 // if Shamt-GRLen < 0: // Shamt < GRLen 240 // Lo = Lo << Shamt 241 // Hi = (Hi << Shamt) | ((Lo >>u 1) >>u (GRLen-1 ^ Shamt)) 242 // else: 243 // Lo = 0 244 // Hi = Lo << (Shamt-GRLen) 245 246 SDValue Zero = DAG.getConstant(0, DL, VT); 247 SDValue One = DAG.getConstant(1, DL, VT); 248 SDValue MinusGRLen = DAG.getConstant(-(int)Subtarget.getGRLen(), DL, VT); 249 SDValue GRLenMinus1 = DAG.getConstant(Subtarget.getGRLen() - 1, DL, VT); 250 SDValue ShamtMinusGRLen = DAG.getNode(ISD::ADD, DL, VT, Shamt, MinusGRLen); 251 SDValue GRLenMinus1Shamt = DAG.getNode(ISD::XOR, DL, VT, Shamt, GRLenMinus1); 252 253 SDValue LoTrue = DAG.getNode(ISD::SHL, DL, VT, Lo, Shamt); 254 SDValue ShiftRight1Lo = DAG.getNode(ISD::SRL, DL, VT, Lo, One); 255 SDValue ShiftRightLo = 256 DAG.getNode(ISD::SRL, DL, VT, ShiftRight1Lo, GRLenMinus1Shamt); 257 SDValue ShiftLeftHi = DAG.getNode(ISD::SHL, DL, VT, Hi, Shamt); 258 SDValue HiTrue = DAG.getNode(ISD::OR, DL, VT, ShiftLeftHi, ShiftRightLo); 259 SDValue HiFalse = DAG.getNode(ISD::SHL, DL, VT, Lo, ShamtMinusGRLen); 260 261 SDValue CC = DAG.getSetCC(DL, VT, ShamtMinusGRLen, Zero, ISD::SETLT); 262 263 Lo = DAG.getNode(ISD::SELECT, DL, VT, CC, LoTrue, Zero); 264 Hi = DAG.getNode(ISD::SELECT, DL, VT, CC, HiTrue, HiFalse); 265 266 SDValue Parts[2] = {Lo, Hi}; 267 return DAG.getMergeValues(Parts, DL); 268 } 269 270 SDValue LoongArchTargetLowering::lowerShiftRightParts(SDValue Op, 271 SelectionDAG &DAG, 272 bool IsSRA) const { 273 SDLoc DL(Op); 274 SDValue Lo = Op.getOperand(0); 275 SDValue Hi = Op.getOperand(1); 276 SDValue Shamt = Op.getOperand(2); 277 EVT VT = Lo.getValueType(); 278 279 // SRA expansion: 280 // if Shamt-GRLen < 0: // Shamt < GRLen 281 // Lo = (Lo >>u Shamt) | ((Hi << 1) << (ShAmt ^ GRLen-1)) 282 // Hi = Hi >>s Shamt 283 // else: 284 // Lo = Hi >>s (Shamt-GRLen); 285 // Hi = Hi >>s (GRLen-1) 286 // 287 // SRL expansion: 288 // if Shamt-GRLen < 0: // Shamt < GRLen 289 // Lo = (Lo >>u Shamt) | ((Hi << 1) << (ShAmt ^ GRLen-1)) 290 // Hi = Hi >>u Shamt 291 // else: 292 // Lo = Hi >>u (Shamt-GRLen); 293 // Hi = 0; 294 295 unsigned ShiftRightOp = IsSRA ? ISD::SRA : ISD::SRL; 296 297 SDValue Zero = DAG.getConstant(0, DL, VT); 298 SDValue One = DAG.getConstant(1, DL, VT); 299 SDValue MinusGRLen = DAG.getConstant(-(int)Subtarget.getGRLen(), DL, VT); 300 SDValue GRLenMinus1 = DAG.getConstant(Subtarget.getGRLen() - 1, DL, VT); 301 SDValue ShamtMinusGRLen = DAG.getNode(ISD::ADD, DL, VT, Shamt, MinusGRLen); 302 SDValue GRLenMinus1Shamt = DAG.getNode(ISD::XOR, DL, VT, Shamt, GRLenMinus1); 303 304 SDValue ShiftRightLo = DAG.getNode(ISD::SRL, DL, VT, Lo, Shamt); 305 SDValue ShiftLeftHi1 = DAG.getNode(ISD::SHL, DL, VT, Hi, One); 306 SDValue ShiftLeftHi = 307 DAG.getNode(ISD::SHL, DL, VT, ShiftLeftHi1, GRLenMinus1Shamt); 308 SDValue LoTrue = DAG.getNode(ISD::OR, DL, VT, ShiftRightLo, ShiftLeftHi); 309 SDValue HiTrue = DAG.getNode(ShiftRightOp, DL, VT, Hi, Shamt); 310 SDValue LoFalse = DAG.getNode(ShiftRightOp, DL, VT, Hi, ShamtMinusGRLen); 311 SDValue HiFalse = 312 IsSRA ? DAG.getNode(ISD::SRA, DL, VT, Hi, GRLenMinus1) : Zero; 313 314 SDValue CC = DAG.getSetCC(DL, VT, ShamtMinusGRLen, Zero, ISD::SETLT); 315 316 Lo = DAG.getNode(ISD::SELECT, DL, VT, CC, LoTrue, LoFalse); 317 Hi = DAG.getNode(ISD::SELECT, DL, VT, CC, HiTrue, HiFalse); 318 319 SDValue Parts[2] = {Lo, Hi}; 320 return DAG.getMergeValues(Parts, DL); 321 } 322 323 // Returns the opcode of the target-specific SDNode that implements the 32-bit 324 // form of the given Opcode. 325 static LoongArchISD::NodeType getLoongArchWOpcode(unsigned Opcode) { 326 switch (Opcode) { 327 default: 328 llvm_unreachable("Unexpected opcode"); 329 case ISD::SHL: 330 return LoongArchISD::SLL_W; 331 case ISD::SRA: 332 return LoongArchISD::SRA_W; 333 case ISD::SRL: 334 return LoongArchISD::SRL_W; 335 } 336 } 337 338 // Converts the given i8/i16/i32 operation to a target-specific SelectionDAG 339 // node. Because i8/i16/i32 isn't a legal type for LA64, these operations would 340 // otherwise be promoted to i64, making it difficult to select the 341 // SLL_W/.../*W later one because the fact the operation was originally of 342 // type i8/i16/i32 is lost. 343 static SDValue customLegalizeToWOp(SDNode *N, SelectionDAG &DAG, 344 unsigned ExtOpc = ISD::ANY_EXTEND) { 345 SDLoc DL(N); 346 LoongArchISD::NodeType WOpcode = getLoongArchWOpcode(N->getOpcode()); 347 SDValue NewOp0 = DAG.getNode(ExtOpc, DL, MVT::i64, N->getOperand(0)); 348 SDValue NewOp1 = DAG.getNode(ExtOpc, DL, MVT::i64, N->getOperand(1)); 349 SDValue NewRes = DAG.getNode(WOpcode, DL, MVT::i64, NewOp0, NewOp1); 350 // ReplaceNodeResults requires we maintain the same type for the return value. 351 return DAG.getNode(ISD::TRUNCATE, DL, N->getValueType(0), NewRes); 352 } 353 354 void LoongArchTargetLowering::ReplaceNodeResults( 355 SDNode *N, SmallVectorImpl<SDValue> &Results, SelectionDAG &DAG) const { 356 SDLoc DL(N); 357 switch (N->getOpcode()) { 358 default: 359 llvm_unreachable("Don't know how to legalize this operation"); 360 case ISD::SHL: 361 case ISD::SRA: 362 case ISD::SRL: 363 assert(N->getValueType(0) == MVT::i32 && Subtarget.is64Bit() && 364 "Unexpected custom legalisation"); 365 if (N->getOperand(1).getOpcode() != ISD::Constant) { 366 Results.push_back(customLegalizeToWOp(N, DAG)); 367 break; 368 } 369 break; 370 case ISD::FP_TO_SINT: { 371 assert(N->getValueType(0) == MVT::i32 && Subtarget.is64Bit() && 372 "Unexpected custom legalisation"); 373 SDValue Src = N->getOperand(0); 374 EVT VT = EVT::getFloatingPointVT(N->getValueSizeInBits(0)); 375 SDValue Dst = DAG.getNode(LoongArchISD::FTINT, DL, VT, Src); 376 Results.push_back(DAG.getNode(ISD::BITCAST, DL, N->getValueType(0), Dst)); 377 break; 378 } 379 case ISD::BITCAST: { 380 EVT VT = N->getValueType(0); 381 SDValue Src = N->getOperand(0); 382 EVT SrcVT = Src.getValueType(); 383 if (VT == MVT::i32 && SrcVT == MVT::f32 && Subtarget.is64Bit() && 384 Subtarget.hasBasicF()) { 385 SDValue Dst = 386 DAG.getNode(LoongArchISD::MOVFR2GR_S_LA64, DL, MVT::i64, Src); 387 Results.push_back(DAG.getNode(ISD::TRUNCATE, DL, MVT::i32, Dst)); 388 } 389 break; 390 } 391 case ISD::FP_TO_UINT: { 392 assert(N->getValueType(0) == MVT::i32 && Subtarget.is64Bit() && 393 "Unexpected custom legalisation"); 394 auto &TLI = DAG.getTargetLoweringInfo(); 395 SDValue Tmp1, Tmp2; 396 TLI.expandFP_TO_UINT(N, Tmp1, Tmp2, DAG); 397 Results.push_back(DAG.getNode(ISD::TRUNCATE, DL, MVT::i32, Tmp1)); 398 break; 399 } 400 } 401 } 402 403 static SDValue performANDCombine(SDNode *N, SelectionDAG &DAG, 404 TargetLowering::DAGCombinerInfo &DCI, 405 const LoongArchSubtarget &Subtarget) { 406 if (DCI.isBeforeLegalizeOps()) 407 return SDValue(); 408 409 SDValue FirstOperand = N->getOperand(0); 410 SDValue SecondOperand = N->getOperand(1); 411 unsigned FirstOperandOpc = FirstOperand.getOpcode(); 412 EVT ValTy = N->getValueType(0); 413 SDLoc DL(N); 414 uint64_t lsb, msb; 415 unsigned SMIdx, SMLen; 416 ConstantSDNode *CN; 417 SDValue NewOperand; 418 MVT GRLenVT = Subtarget.getGRLenVT(); 419 420 // Op's second operand must be a shifted mask. 421 if (!(CN = dyn_cast<ConstantSDNode>(SecondOperand)) || 422 !isShiftedMask_64(CN->getZExtValue(), SMIdx, SMLen)) 423 return SDValue(); 424 425 if (FirstOperandOpc == ISD::SRA || FirstOperandOpc == ISD::SRL) { 426 // Pattern match BSTRPICK. 427 // $dst = and ((sra or srl) $src , lsb), (2**len - 1) 428 // => BSTRPICK $dst, $src, msb, lsb 429 // where msb = lsb + len - 1 430 431 // The second operand of the shift must be an immediate. 432 if (!(CN = dyn_cast<ConstantSDNode>(FirstOperand.getOperand(1)))) 433 return SDValue(); 434 435 lsb = CN->getZExtValue(); 436 437 // Return if the shifted mask does not start at bit 0 or the sum of its 438 // length and lsb exceeds the word's size. 439 if (SMIdx != 0 || lsb + SMLen > ValTy.getSizeInBits()) 440 return SDValue(); 441 442 NewOperand = FirstOperand.getOperand(0); 443 } else { 444 // Pattern match BSTRPICK. 445 // $dst = and $src, (2**len- 1) , if len > 12 446 // => BSTRPICK $dst, $src, msb, lsb 447 // where lsb = 0 and msb = len - 1 448 449 // If the mask is <= 0xfff, andi can be used instead. 450 if (CN->getZExtValue() <= 0xfff) 451 return SDValue(); 452 453 // Return if the mask doesn't start at position 0. 454 if (SMIdx) 455 return SDValue(); 456 457 lsb = 0; 458 NewOperand = FirstOperand; 459 } 460 msb = lsb + SMLen - 1; 461 return DAG.getNode(LoongArchISD::BSTRPICK, DL, ValTy, NewOperand, 462 DAG.getConstant(msb, DL, GRLenVT), 463 DAG.getConstant(lsb, DL, GRLenVT)); 464 } 465 466 static SDValue performSRLCombine(SDNode *N, SelectionDAG &DAG, 467 TargetLowering::DAGCombinerInfo &DCI, 468 const LoongArchSubtarget &Subtarget) { 469 if (DCI.isBeforeLegalizeOps()) 470 return SDValue(); 471 472 // $dst = srl (and $src, Mask), Shamt 473 // => 474 // BSTRPICK $dst, $src, MaskIdx+MaskLen-1, Shamt 475 // when Mask is a shifted mask, and MaskIdx <= Shamt <= MaskIdx+MaskLen-1 476 // 477 478 SDValue FirstOperand = N->getOperand(0); 479 ConstantSDNode *CN; 480 EVT ValTy = N->getValueType(0); 481 SDLoc DL(N); 482 MVT GRLenVT = Subtarget.getGRLenVT(); 483 unsigned MaskIdx, MaskLen; 484 uint64_t Shamt; 485 486 // The first operand must be an AND and the second operand of the AND must be 487 // a shifted mask. 488 if (FirstOperand.getOpcode() != ISD::AND || 489 !(CN = dyn_cast<ConstantSDNode>(FirstOperand.getOperand(1))) || 490 !isShiftedMask_64(CN->getZExtValue(), MaskIdx, MaskLen)) 491 return SDValue(); 492 493 // The second operand (shift amount) must be an immediate. 494 if (!(CN = dyn_cast<ConstantSDNode>(N->getOperand(1)))) 495 return SDValue(); 496 497 Shamt = CN->getZExtValue(); 498 if (MaskIdx <= Shamt && Shamt <= MaskIdx + MaskLen - 1) 499 return DAG.getNode(LoongArchISD::BSTRPICK, DL, ValTy, 500 FirstOperand->getOperand(0), 501 DAG.getConstant(MaskIdx + MaskLen - 1, DL, GRLenVT), 502 DAG.getConstant(Shamt, DL, GRLenVT)); 503 504 return SDValue(); 505 } 506 507 static SDValue performORCombine(SDNode *N, SelectionDAG &DAG, 508 TargetLowering::DAGCombinerInfo &DCI, 509 const LoongArchSubtarget &Subtarget) { 510 MVT GRLenVT = Subtarget.getGRLenVT(); 511 EVT ValTy = N->getValueType(0); 512 SDValue N0 = N->getOperand(0), N1 = N->getOperand(1); 513 ConstantSDNode *CN0, *CN1; 514 SDLoc DL(N); 515 unsigned ValBits = ValTy.getSizeInBits(); 516 unsigned MaskIdx0, MaskLen0, MaskIdx1, MaskLen1; 517 unsigned Shamt; 518 bool SwapAndRetried = false; 519 520 if (DCI.isBeforeLegalizeOps()) 521 return SDValue(); 522 523 if (ValBits != 32 && ValBits != 64) 524 return SDValue(); 525 526 Retry: 527 // 1st pattern to match BSTRINS: 528 // R = or (and X, mask0), (and (shl Y, lsb), mask1) 529 // where mask1 = (2**size - 1) << lsb, mask0 = ~mask1 530 // => 531 // R = BSTRINS X, Y, msb, lsb (where msb = lsb + size - 1) 532 if (N0.getOpcode() == ISD::AND && 533 (CN0 = dyn_cast<ConstantSDNode>(N0.getOperand(1))) && 534 isShiftedMask_64(~CN0->getSExtValue(), MaskIdx0, MaskLen0) && 535 N1.getOpcode() == ISD::AND && N1.getOperand(0).getOpcode() == ISD::SHL && 536 (CN1 = dyn_cast<ConstantSDNode>(N1.getOperand(1))) && 537 isShiftedMask_64(CN1->getZExtValue(), MaskIdx1, MaskLen1) && 538 MaskIdx0 == MaskIdx1 && MaskLen0 == MaskLen1 && 539 (CN1 = dyn_cast<ConstantSDNode>(N1.getOperand(0).getOperand(1))) && 540 (Shamt = CN1->getZExtValue()) == MaskIdx0 && 541 (MaskIdx0 + MaskLen0 <= ValBits)) { 542 LLVM_DEBUG(dbgs() << "Perform OR combine: match pattern 1\n"); 543 return DAG.getNode(LoongArchISD::BSTRINS, DL, ValTy, N0.getOperand(0), 544 N1.getOperand(0).getOperand(0), 545 DAG.getConstant((MaskIdx0 + MaskLen0 - 1), DL, GRLenVT), 546 DAG.getConstant(MaskIdx0, DL, GRLenVT)); 547 } 548 549 // 2nd pattern to match BSTRINS: 550 // R = or (and X, mask0), (shl (and Y, mask1), lsb) 551 // where mask1 = (2**size - 1), mask0 = ~(mask1 << lsb) 552 // => 553 // R = BSTRINS X, Y, msb, lsb (where msb = lsb + size - 1) 554 if (N0.getOpcode() == ISD::AND && 555 (CN0 = dyn_cast<ConstantSDNode>(N0.getOperand(1))) && 556 isShiftedMask_64(~CN0->getSExtValue(), MaskIdx0, MaskLen0) && 557 N1.getOpcode() == ISD::SHL && N1.getOperand(0).getOpcode() == ISD::AND && 558 (CN1 = dyn_cast<ConstantSDNode>(N1.getOperand(1))) && 559 (Shamt = CN1->getZExtValue()) == MaskIdx0 && 560 (CN1 = dyn_cast<ConstantSDNode>(N1.getOperand(0).getOperand(1))) && 561 isShiftedMask_64(CN1->getZExtValue(), MaskIdx1, MaskLen1) && 562 MaskLen0 == MaskLen1 && MaskIdx1 == 0 && 563 (MaskIdx0 + MaskLen0 <= ValBits)) { 564 LLVM_DEBUG(dbgs() << "Perform OR combine: match pattern 2\n"); 565 return DAG.getNode(LoongArchISD::BSTRINS, DL, ValTy, N0.getOperand(0), 566 N1.getOperand(0).getOperand(0), 567 DAG.getConstant((MaskIdx0 + MaskLen0 - 1), DL, GRLenVT), 568 DAG.getConstant(MaskIdx0, DL, GRLenVT)); 569 } 570 571 // 3rd pattern to match BSTRINS: 572 // R = or (and X, mask0), (and Y, mask1) 573 // where ~mask0 = (2**size - 1) << lsb, mask0 & mask1 = 0 574 // => 575 // R = BSTRINS X, (shr (and Y, mask1), lsb), msb, lsb 576 // where msb = lsb + size - 1 577 if (N0.getOpcode() == ISD::AND && N1.getOpcode() == ISD::AND && 578 (CN0 = dyn_cast<ConstantSDNode>(N0.getOperand(1))) && 579 isShiftedMask_64(~CN0->getSExtValue(), MaskIdx0, MaskLen0) && 580 (MaskIdx0 + MaskLen0 <= 64) && 581 (CN1 = dyn_cast<ConstantSDNode>(N1->getOperand(1))) && 582 (CN1->getSExtValue() & CN0->getSExtValue()) == 0) { 583 LLVM_DEBUG(dbgs() << "Perform OR combine: match pattern 3\n"); 584 return DAG.getNode(LoongArchISD::BSTRINS, DL, ValTy, N0.getOperand(0), 585 DAG.getNode(ISD::SRL, DL, N1->getValueType(0), N1, 586 DAG.getConstant(MaskIdx0, DL, GRLenVT)), 587 DAG.getConstant(ValBits == 32 588 ? (MaskIdx0 + (MaskLen0 & 31) - 1) 589 : (MaskIdx0 + MaskLen0 - 1), 590 DL, GRLenVT), 591 DAG.getConstant(MaskIdx0, DL, GRLenVT)); 592 } 593 594 // 4th pattern to match BSTRINS: 595 // R = or (and X, mask), (shl Y, shamt) 596 // where mask = (2**shamt - 1) 597 // => 598 // R = BSTRINS X, Y, ValBits - 1, shamt 599 // where ValBits = 32 or 64 600 if (N0.getOpcode() == ISD::AND && N1.getOpcode() == ISD::SHL && 601 (CN0 = dyn_cast<ConstantSDNode>(N0.getOperand(1))) && 602 isShiftedMask_64(CN0->getZExtValue(), MaskIdx0, MaskLen0) && 603 MaskIdx0 == 0 && (CN1 = dyn_cast<ConstantSDNode>(N1.getOperand(1))) && 604 (Shamt = CN1->getZExtValue()) == MaskLen0 && 605 (MaskIdx0 + MaskLen0 <= ValBits)) { 606 LLVM_DEBUG(dbgs() << "Perform OR combine: match pattern 4\n"); 607 return DAG.getNode(LoongArchISD::BSTRINS, DL, ValTy, N0.getOperand(0), 608 N1.getOperand(0), 609 DAG.getConstant((ValBits - 1), DL, GRLenVT), 610 DAG.getConstant(Shamt, DL, GRLenVT)); 611 } 612 613 // 5th pattern to match BSTRINS: 614 // R = or (and X, mask), const 615 // where ~mask = (2**size - 1) << lsb, mask & const = 0 616 // => 617 // R = BSTRINS X, (const >> lsb), msb, lsb 618 // where msb = lsb + size - 1 619 if (N0.getOpcode() == ISD::AND && 620 (CN0 = dyn_cast<ConstantSDNode>(N0.getOperand(1))) && 621 isShiftedMask_64(~CN0->getSExtValue(), MaskIdx0, MaskLen0) && 622 (CN1 = dyn_cast<ConstantSDNode>(N1)) && 623 (CN1->getSExtValue() & CN0->getSExtValue()) == 0) { 624 LLVM_DEBUG(dbgs() << "Perform OR combine: match pattern 5\n"); 625 return DAG.getNode( 626 LoongArchISD::BSTRINS, DL, ValTy, N0.getOperand(0), 627 DAG.getConstant(CN1->getSExtValue() >> MaskIdx0, DL, ValTy), 628 DAG.getConstant((MaskIdx0 + MaskLen0 - 1), DL, GRLenVT), 629 DAG.getConstant(MaskIdx0, DL, GRLenVT)); 630 } 631 632 // 6th pattern. 633 // a = b | ((c & mask) << shamt), where all positions in b to be overwritten 634 // by the incoming bits are known to be zero. 635 // => 636 // a = BSTRINS b, c, shamt + MaskLen - 1, shamt 637 // 638 // Note that the 1st pattern is a special situation of the 6th, i.e. the 6th 639 // pattern is more common than the 1st. So we put the 1st before the 6th in 640 // order to match as many nodes as possible. 641 ConstantSDNode *CNMask, *CNShamt; 642 unsigned MaskIdx, MaskLen; 643 if (N1.getOpcode() == ISD::SHL && N1.getOperand(0).getOpcode() == ISD::AND && 644 (CNMask = dyn_cast<ConstantSDNode>(N1.getOperand(0).getOperand(1))) && 645 isShiftedMask_64(CNMask->getZExtValue(), MaskIdx, MaskLen) && 646 MaskIdx == 0 && (CNShamt = dyn_cast<ConstantSDNode>(N1.getOperand(1))) && 647 CNShamt->getZExtValue() + MaskLen <= ValBits) { 648 Shamt = CNShamt->getZExtValue(); 649 APInt ShMask(ValBits, CNMask->getZExtValue() << Shamt); 650 if (ShMask.isSubsetOf(DAG.computeKnownBits(N0).Zero)) { 651 LLVM_DEBUG(dbgs() << "Perform OR combine: match pattern 6\n"); 652 return DAG.getNode(LoongArchISD::BSTRINS, DL, ValTy, N0, 653 N1.getOperand(0).getOperand(0), 654 DAG.getConstant(Shamt + MaskLen - 1, DL, GRLenVT), 655 DAG.getConstant(Shamt, DL, GRLenVT)); 656 } 657 } 658 659 // 7th pattern. 660 // a = b | ((c << shamt) & shifted_mask), where all positions in b to be 661 // overwritten by the incoming bits are known to be zero. 662 // => 663 // a = BSTRINS b, c, MaskIdx + MaskLen - 1, MaskIdx 664 // 665 // Similarly, the 7th pattern is more common than the 2nd. So we put the 2nd 666 // before the 7th in order to match as many nodes as possible. 667 if (N1.getOpcode() == ISD::AND && 668 (CNMask = dyn_cast<ConstantSDNode>(N1.getOperand(1))) && 669 isShiftedMask_64(CNMask->getZExtValue(), MaskIdx, MaskLen) && 670 N1.getOperand(0).getOpcode() == ISD::SHL && 671 (CNShamt = dyn_cast<ConstantSDNode>(N1.getOperand(0).getOperand(1))) && 672 CNShamt->getZExtValue() == MaskIdx) { 673 APInt ShMask(ValBits, CNMask->getZExtValue()); 674 if (ShMask.isSubsetOf(DAG.computeKnownBits(N0).Zero)) { 675 LLVM_DEBUG(dbgs() << "Perform OR combine: match pattern 7\n"); 676 return DAG.getNode(LoongArchISD::BSTRINS, DL, ValTy, N0, 677 N1.getOperand(0).getOperand(0), 678 DAG.getConstant(MaskIdx + MaskLen - 1, DL, GRLenVT), 679 DAG.getConstant(MaskIdx, DL, GRLenVT)); 680 } 681 } 682 683 // (or a, b) and (or b, a) are equivalent, so swap the operands and retry. 684 if (!SwapAndRetried) { 685 std::swap(N0, N1); 686 SwapAndRetried = true; 687 goto Retry; 688 } 689 690 SwapAndRetried = false; 691 Retry2: 692 // 8th pattern. 693 // a = b | (c & shifted_mask), where all positions in b to be overwritten by 694 // the incoming bits are known to be zero. 695 // => 696 // a = BSTRINS b, c >> MaskIdx, MaskIdx + MaskLen - 1, MaskIdx 697 // 698 // Similarly, the 8th pattern is more common than the 4th and 5th patterns. So 699 // we put it here in order to match as many nodes as possible or generate less 700 // instructions. 701 if (N1.getOpcode() == ISD::AND && 702 (CNMask = dyn_cast<ConstantSDNode>(N1.getOperand(1))) && 703 isShiftedMask_64(CNMask->getZExtValue(), MaskIdx, MaskLen)) { 704 APInt ShMask(ValBits, CNMask->getZExtValue()); 705 if (ShMask.isSubsetOf(DAG.computeKnownBits(N0).Zero)) { 706 LLVM_DEBUG(dbgs() << "Perform OR combine: match pattern 8\n"); 707 return DAG.getNode(LoongArchISD::BSTRINS, DL, ValTy, N0, 708 DAG.getNode(ISD::SRL, DL, N1->getValueType(0), 709 N1->getOperand(0), 710 DAG.getConstant(MaskIdx, DL, GRLenVT)), 711 DAG.getConstant(MaskIdx + MaskLen - 1, DL, GRLenVT), 712 DAG.getConstant(MaskIdx, DL, GRLenVT)); 713 } 714 } 715 // Swap N0/N1 and retry. 716 if (!SwapAndRetried) { 717 std::swap(N0, N1); 718 SwapAndRetried = true; 719 goto Retry2; 720 } 721 722 return SDValue(); 723 } 724 725 SDValue LoongArchTargetLowering::PerformDAGCombine(SDNode *N, 726 DAGCombinerInfo &DCI) const { 727 SelectionDAG &DAG = DCI.DAG; 728 switch (N->getOpcode()) { 729 default: 730 break; 731 case ISD::AND: 732 return performANDCombine(N, DAG, DCI, Subtarget); 733 case ISD::OR: 734 return performORCombine(N, DAG, DCI, Subtarget); 735 case ISD::SRL: 736 return performSRLCombine(N, DAG, DCI, Subtarget); 737 } 738 return SDValue(); 739 } 740 741 static MachineBasicBlock *insertDivByZeroTrap(MachineInstr &MI, 742 MachineBasicBlock &MBB, 743 const TargetInstrInfo &TII) { 744 if (!ZeroDivCheck) 745 return &MBB; 746 747 // Build instructions: 748 // div(or mod) $dst, $dividend, $divisor 749 // bnez $divisor, 8 750 // break 7 751 // fallthrough 752 MachineOperand &Divisor = MI.getOperand(2); 753 auto FallThrough = std::next(MI.getIterator()); 754 755 BuildMI(MBB, FallThrough, MI.getDebugLoc(), TII.get(LoongArch::BNEZ)) 756 .addReg(Divisor.getReg(), getKillRegState(Divisor.isKill())) 757 .addImm(8); 758 759 // See linux header file arch/loongarch/include/uapi/asm/break.h for the 760 // definition of BRK_DIVZERO. 761 BuildMI(MBB, FallThrough, MI.getDebugLoc(), TII.get(LoongArch::BREAK)) 762 .addImm(7/*BRK_DIVZERO*/); 763 764 // Clear Divisor's kill flag. 765 Divisor.setIsKill(false); 766 767 return &MBB; 768 } 769 770 MachineBasicBlock *LoongArchTargetLowering::EmitInstrWithCustomInserter( 771 MachineInstr &MI, MachineBasicBlock *BB) const { 772 773 switch (MI.getOpcode()) { 774 default: 775 llvm_unreachable("Unexpected instr type to insert"); 776 case LoongArch::DIV_W: 777 case LoongArch::DIV_WU: 778 case LoongArch::MOD_W: 779 case LoongArch::MOD_WU: 780 case LoongArch::DIV_D: 781 case LoongArch::DIV_DU: 782 case LoongArch::MOD_D: 783 case LoongArch::MOD_DU: 784 return insertDivByZeroTrap(MI, *BB, *Subtarget.getInstrInfo()); 785 break; 786 } 787 } 788 789 const char *LoongArchTargetLowering::getTargetNodeName(unsigned Opcode) const { 790 switch ((LoongArchISD::NodeType)Opcode) { 791 case LoongArchISD::FIRST_NUMBER: 792 break; 793 794 #define NODE_NAME_CASE(node) \ 795 case LoongArchISD::node: \ 796 return "LoongArchISD::" #node; 797 798 // TODO: Add more target-dependent nodes later. 799 NODE_NAME_CASE(CALL) 800 NODE_NAME_CASE(RET) 801 NODE_NAME_CASE(SLL_W) 802 NODE_NAME_CASE(SRA_W) 803 NODE_NAME_CASE(SRL_W) 804 NODE_NAME_CASE(BSTRINS) 805 NODE_NAME_CASE(BSTRPICK) 806 NODE_NAME_CASE(MOVGR2FR_W_LA64) 807 NODE_NAME_CASE(MOVFR2GR_S_LA64) 808 NODE_NAME_CASE(FTINT) 809 } 810 #undef NODE_NAME_CASE 811 return nullptr; 812 } 813 814 //===----------------------------------------------------------------------===// 815 // Calling Convention Implementation 816 //===----------------------------------------------------------------------===// 817 // FIXME: Now, we only support CallingConv::C with fixed arguments which are 818 // passed with integer or floating-point registers. 819 const MCPhysReg ArgGPRs[] = {LoongArch::R4, LoongArch::R5, LoongArch::R6, 820 LoongArch::R7, LoongArch::R8, LoongArch::R9, 821 LoongArch::R10, LoongArch::R11}; 822 const MCPhysReg ArgFPR32s[] = {LoongArch::F0, LoongArch::F1, LoongArch::F2, 823 LoongArch::F3, LoongArch::F4, LoongArch::F5, 824 LoongArch::F6, LoongArch::F7}; 825 const MCPhysReg ArgFPR64s[] = { 826 LoongArch::F0_64, LoongArch::F1_64, LoongArch::F2_64, LoongArch::F3_64, 827 LoongArch::F4_64, LoongArch::F5_64, LoongArch::F6_64, LoongArch::F7_64}; 828 829 // Implements the LoongArch calling convention. Returns true upon failure. 830 static bool CC_LoongArch(unsigned ValNo, MVT ValVT, 831 CCValAssign::LocInfo LocInfo, CCState &State) { 832 // Allocate to a register if possible. 833 Register Reg; 834 835 if (ValVT == MVT::f32) 836 Reg = State.AllocateReg(ArgFPR32s); 837 else if (ValVT == MVT::f64) 838 Reg = State.AllocateReg(ArgFPR64s); 839 else 840 Reg = State.AllocateReg(ArgGPRs); 841 if (Reg) { 842 State.addLoc(CCValAssign::getReg(ValNo, ValVT, Reg, ValVT, LocInfo)); 843 return false; 844 } 845 846 // TODO: Handle arguments passed without register. 847 return true; 848 } 849 850 void LoongArchTargetLowering::analyzeInputArgs( 851 CCState &CCInfo, const SmallVectorImpl<ISD::InputArg> &Ins, 852 LoongArchCCAssignFn Fn) const { 853 for (unsigned i = 0, e = Ins.size(); i != e; ++i) { 854 MVT ArgVT = Ins[i].VT; 855 856 if (Fn(i, ArgVT, CCValAssign::Full, CCInfo)) { 857 LLVM_DEBUG(dbgs() << "InputArg #" << i << " has unhandled type " 858 << EVT(ArgVT).getEVTString() << '\n'); 859 llvm_unreachable(""); 860 } 861 } 862 } 863 864 void LoongArchTargetLowering::analyzeOutputArgs( 865 CCState &CCInfo, const SmallVectorImpl<ISD::OutputArg> &Outs, 866 LoongArchCCAssignFn Fn) const { 867 for (unsigned i = 0, e = Outs.size(); i != e; ++i) { 868 MVT ArgVT = Outs[i].VT; 869 870 if (Fn(i, ArgVT, CCValAssign::Full, CCInfo)) { 871 LLVM_DEBUG(dbgs() << "OutputArg #" << i << " has unhandled type " 872 << EVT(ArgVT).getEVTString() << "\n"); 873 llvm_unreachable(""); 874 } 875 } 876 } 877 878 static SDValue unpackFromRegLoc(SelectionDAG &DAG, SDValue Chain, 879 const CCValAssign &VA, const SDLoc &DL, 880 const LoongArchTargetLowering &TLI) { 881 MachineFunction &MF = DAG.getMachineFunction(); 882 MachineRegisterInfo &RegInfo = MF.getRegInfo(); 883 EVT LocVT = VA.getLocVT(); 884 const TargetRegisterClass *RC = TLI.getRegClassFor(LocVT.getSimpleVT()); 885 Register VReg = RegInfo.createVirtualRegister(RC); 886 RegInfo.addLiveIn(VA.getLocReg(), VReg); 887 888 return DAG.getCopyFromReg(Chain, DL, VReg, LocVT); 889 } 890 891 // Transform physical registers into virtual registers. 892 SDValue LoongArchTargetLowering::LowerFormalArguments( 893 SDValue Chain, CallingConv::ID CallConv, bool IsVarArg, 894 const SmallVectorImpl<ISD::InputArg> &Ins, const SDLoc &DL, 895 SelectionDAG &DAG, SmallVectorImpl<SDValue> &InVals) const { 896 897 MachineFunction &MF = DAG.getMachineFunction(); 898 899 switch (CallConv) { 900 default: 901 llvm_unreachable("Unsupported calling convention"); 902 case CallingConv::C: 903 break; 904 } 905 906 // Assign locations to all of the incoming arguments. 907 SmallVector<CCValAssign> ArgLocs; 908 CCState CCInfo(CallConv, IsVarArg, MF, ArgLocs, *DAG.getContext()); 909 910 analyzeInputArgs(CCInfo, Ins, CC_LoongArch); 911 912 for (unsigned i = 0, e = ArgLocs.size(); i != e; ++i) 913 InVals.push_back(unpackFromRegLoc(DAG, Chain, ArgLocs[i], DL, *this)); 914 915 return Chain; 916 } 917 918 // Lower a call to a callseq_start + CALL + callseq_end chain, and add input 919 // and output parameter nodes. 920 SDValue 921 LoongArchTargetLowering::LowerCall(CallLoweringInfo &CLI, 922 SmallVectorImpl<SDValue> &InVals) const { 923 SelectionDAG &DAG = CLI.DAG; 924 SDLoc &DL = CLI.DL; 925 SmallVectorImpl<ISD::OutputArg> &Outs = CLI.Outs; 926 SmallVectorImpl<SDValue> &OutVals = CLI.OutVals; 927 SmallVectorImpl<ISD::InputArg> &Ins = CLI.Ins; 928 SDValue Chain = CLI.Chain; 929 SDValue Callee = CLI.Callee; 930 CallingConv::ID CallConv = CLI.CallConv; 931 bool IsVarArg = CLI.IsVarArg; 932 EVT PtrVT = getPointerTy(DAG.getDataLayout()); 933 CLI.IsTailCall = false; 934 935 if (IsVarArg) 936 report_fatal_error("LowerCall with varargs not implemented"); 937 938 MachineFunction &MF = DAG.getMachineFunction(); 939 940 // Analyze the operands of the call, assigning locations to each operand. 941 SmallVector<CCValAssign> ArgLocs; 942 CCState ArgCCInfo(CallConv, IsVarArg, MF, ArgLocs, *DAG.getContext()); 943 944 analyzeOutputArgs(ArgCCInfo, Outs, CC_LoongArch); 945 946 // Get a count of how many bytes are to be pushed on the stack. 947 unsigned NumBytes = ArgCCInfo.getNextStackOffset(); 948 949 for (auto &Arg : Outs) { 950 if (!Arg.Flags.isByVal()) 951 continue; 952 report_fatal_error("Passing arguments byval not implemented"); 953 } 954 955 Chain = DAG.getCALLSEQ_START(Chain, NumBytes, 0, CLI.DL); 956 957 // Copy argument values to their designated locations. 958 SmallVector<std::pair<Register, SDValue>> RegsToPass; 959 for (unsigned i = 0, e = ArgLocs.size(); i != e; ++i) { 960 CCValAssign &VA = ArgLocs[i]; 961 SDValue ArgValue = OutVals[i]; 962 963 // Promote the value if needed. 964 // For now, only handle fully promoted arguments. 965 if (VA.getLocInfo() != CCValAssign::Full) 966 report_fatal_error("Unknown loc info"); 967 968 if (VA.isRegLoc()) { 969 // Queue up the argument copies and emit them at the end. 970 RegsToPass.push_back(std::make_pair(VA.getLocReg(), ArgValue)); 971 } else { 972 report_fatal_error("Passing arguments via the stack not implemented"); 973 } 974 } 975 976 SDValue Glue; 977 978 // Build a sequence of copy-to-reg nodes, chained and glued together. 979 for (auto &Reg : RegsToPass) { 980 Chain = DAG.getCopyToReg(Chain, DL, Reg.first, Reg.second, Glue); 981 Glue = Chain.getValue(1); 982 } 983 984 // If the callee is a GlobalAddress/ExternalSymbol node, turn it into a 985 // TargetGlobalAddress/TargetExternalSymbol node so that legalize won't 986 // split it and then direct call can be matched by PseudoCALL. 987 // FIXME: Add target flags for relocation. 988 if (GlobalAddressSDNode *S = dyn_cast<GlobalAddressSDNode>(Callee)) 989 Callee = DAG.getTargetGlobalAddress(S->getGlobal(), DL, PtrVT); 990 else if (ExternalSymbolSDNode *S = dyn_cast<ExternalSymbolSDNode>(Callee)) 991 Callee = DAG.getTargetExternalSymbol(S->getSymbol(), PtrVT); 992 993 // The first call operand is the chain and the second is the target address. 994 SmallVector<SDValue> Ops; 995 Ops.push_back(Chain); 996 Ops.push_back(Callee); 997 998 // Add argument registers to the end of the list so that they are 999 // known live into the call. 1000 for (auto &Reg : RegsToPass) 1001 Ops.push_back(DAG.getRegister(Reg.first, Reg.second.getValueType())); 1002 1003 // Add a register mask operand representing the call-preserved registers. 1004 const TargetRegisterInfo *TRI = Subtarget.getRegisterInfo(); 1005 const uint32_t *Mask = TRI->getCallPreservedMask(MF, CallConv); 1006 assert(Mask && "Missing call preserved mask for calling convention"); 1007 Ops.push_back(DAG.getRegisterMask(Mask)); 1008 1009 // Glue the call to the argument copies, if any. 1010 if (Glue.getNode()) 1011 Ops.push_back(Glue); 1012 1013 // Emit the call. 1014 SDVTList NodeTys = DAG.getVTList(MVT::Other, MVT::Glue); 1015 1016 Chain = DAG.getNode(LoongArchISD::CALL, DL, NodeTys, Ops); 1017 DAG.addNoMergeSiteInfo(Chain.getNode(), CLI.NoMerge); 1018 Glue = Chain.getValue(1); 1019 1020 // Mark the end of the call, which is glued to the call itself. 1021 Chain = DAG.getCALLSEQ_END(Chain, DAG.getConstant(NumBytes, DL, PtrVT, true), 1022 DAG.getConstant(0, DL, PtrVT, true), Glue, DL); 1023 Glue = Chain.getValue(1); 1024 1025 // Assign locations to each value returned by this call. 1026 SmallVector<CCValAssign> RVLocs; 1027 CCState RetCCInfo(CallConv, IsVarArg, MF, RVLocs, *DAG.getContext()); 1028 analyzeInputArgs(RetCCInfo, Ins, CC_LoongArch); 1029 1030 // Copy all of the result registers out of their specified physreg. 1031 for (auto &VA : RVLocs) { 1032 // Copy the value out. 1033 SDValue RetValue = 1034 DAG.getCopyFromReg(Chain, DL, VA.getLocReg(), VA.getLocVT(), Glue); 1035 Chain = RetValue.getValue(1); 1036 Glue = RetValue.getValue(2); 1037 1038 InVals.push_back(Chain.getValue(0)); 1039 } 1040 1041 return Chain; 1042 } 1043 1044 bool LoongArchTargetLowering::CanLowerReturn( 1045 CallingConv::ID CallConv, MachineFunction &MF, bool IsVarArg, 1046 const SmallVectorImpl<ISD::OutputArg> &Outs, LLVMContext &Context) const { 1047 // Any return value split in to more than two values can't be returned 1048 // directly. 1049 return Outs.size() <= 2; 1050 } 1051 1052 SDValue LoongArchTargetLowering::LowerReturn( 1053 SDValue Chain, CallingConv::ID CallConv, bool IsVarArg, 1054 const SmallVectorImpl<ISD::OutputArg> &Outs, 1055 const SmallVectorImpl<SDValue> &OutVals, const SDLoc &DL, 1056 SelectionDAG &DAG) const { 1057 // Stores the assignment of the return value to a location. 1058 SmallVector<CCValAssign> RVLocs; 1059 1060 // Info about the registers and stack slot. 1061 CCState CCInfo(CallConv, IsVarArg, DAG.getMachineFunction(), RVLocs, 1062 *DAG.getContext()); 1063 1064 analyzeOutputArgs(CCInfo, Outs, CC_LoongArch); 1065 1066 SDValue Glue; 1067 SmallVector<SDValue, 4> RetOps(1, Chain); 1068 1069 // Copy the result values into the output registers. 1070 for (unsigned i = 0, e = RVLocs.size(); i < e; ++i) { 1071 CCValAssign &VA = RVLocs[i]; 1072 assert(VA.isRegLoc() && "Can only return in registers!"); 1073 1074 // Handle a 'normal' return. 1075 Chain = DAG.getCopyToReg(Chain, DL, VA.getLocReg(), OutVals[i], Glue); 1076 1077 // Guarantee that all emitted copies are stuck together. 1078 Glue = Chain.getValue(1); 1079 RetOps.push_back(DAG.getRegister(VA.getLocReg(), VA.getLocVT())); 1080 } 1081 1082 RetOps[0] = Chain; // Update chain. 1083 1084 // Add the glue node if we have it. 1085 if (Glue.getNode()) 1086 RetOps.push_back(Glue); 1087 1088 return DAG.getNode(LoongArchISD::RET, DL, MVT::Other, RetOps); 1089 } 1090 1091 bool LoongArchTargetLowering::isFPImmLegal(const APFloat &Imm, EVT VT, 1092 bool ForCodeSize) const { 1093 assert((VT == MVT::f32 || VT == MVT::f64) && "Unexpected VT"); 1094 1095 if (VT == MVT::f32 && !Subtarget.hasBasicF()) 1096 return false; 1097 if (VT == MVT::f64 && !Subtarget.hasBasicD()) 1098 return false; 1099 return (Imm.isZero() || Imm.isExactlyValue(+1.0)); 1100 } 1101