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