1 //=- LoongArchISelDAGToDAG.cpp - A dag to dag inst selector for LoongArch -===// 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 an instruction selector for the LoongArch target. 10 // 11 //===----------------------------------------------------------------------===// 12 13 #include "LoongArchISelDAGToDAG.h" 14 #include "LoongArchISelLowering.h" 15 #include "MCTargetDesc/LoongArchMCTargetDesc.h" 16 #include "MCTargetDesc/LoongArchMatInt.h" 17 #include "llvm/Support/KnownBits.h" 18 #include "llvm/Support/raw_ostream.h" 19 20 using namespace llvm; 21 22 #define DEBUG_TYPE "loongarch-isel" 23 #define PASS_NAME "LoongArch DAG->DAG Pattern Instruction Selection" 24 25 char LoongArchDAGToDAGISel::ID; 26 27 INITIALIZE_PASS(LoongArchDAGToDAGISel, DEBUG_TYPE, PASS_NAME, false, false) 28 29 void LoongArchDAGToDAGISel::Select(SDNode *Node) { 30 // If we have a custom node, we have already selected. 31 if (Node->isMachineOpcode()) { 32 LLVM_DEBUG(dbgs() << "== "; Node->dump(CurDAG); dbgs() << "\n"); 33 Node->setNodeId(-1); 34 return; 35 } 36 37 // Instruction Selection not handled by the auto-generated tablegen selection 38 // should be handled here. 39 unsigned Opcode = Node->getOpcode(); 40 MVT GRLenVT = Subtarget->getGRLenVT(); 41 SDLoc DL(Node); 42 MVT VT = Node->getSimpleValueType(0); 43 44 switch (Opcode) { 45 default: 46 break; 47 case ISD::Constant: { 48 int64_t Imm = cast<ConstantSDNode>(Node)->getSExtValue(); 49 if (Imm == 0 && VT == GRLenVT) { 50 SDValue New = CurDAG->getCopyFromReg(CurDAG->getEntryNode(), DL, 51 LoongArch::R0, GRLenVT); 52 ReplaceNode(Node, New.getNode()); 53 return; 54 } 55 SDNode *Result = nullptr; 56 SDValue SrcReg = CurDAG->getRegister(LoongArch::R0, GRLenVT); 57 // The instructions in the sequence are handled here. 58 for (LoongArchMatInt::Inst &Inst : LoongArchMatInt::generateInstSeq(Imm)) { 59 SDValue SDImm = CurDAG->getTargetConstant(Inst.Imm, DL, GRLenVT); 60 if (Inst.Opc == LoongArch::LU12I_W) 61 Result = CurDAG->getMachineNode(LoongArch::LU12I_W, DL, GRLenVT, SDImm); 62 else 63 Result = CurDAG->getMachineNode(Inst.Opc, DL, GRLenVT, SrcReg, SDImm); 64 SrcReg = SDValue(Result, 0); 65 } 66 67 ReplaceNode(Node, Result); 68 return; 69 } 70 case ISD::FrameIndex: { 71 SDValue Imm = CurDAG->getTargetConstant(0, DL, GRLenVT); 72 int FI = cast<FrameIndexSDNode>(Node)->getIndex(); 73 SDValue TFI = CurDAG->getTargetFrameIndex(FI, VT); 74 unsigned ADDIOp = 75 Subtarget->is64Bit() ? LoongArch::ADDI_D : LoongArch::ADDI_W; 76 ReplaceNode(Node, CurDAG->getMachineNode(ADDIOp, DL, VT, TFI, Imm)); 77 return; 78 } 79 case ISD::BITCAST: { 80 if (VT.is128BitVector() || VT.is256BitVector()) { 81 ReplaceUses(SDValue(Node, 0), Node->getOperand(0)); 82 CurDAG->RemoveDeadNode(Node); 83 return; 84 } 85 break; 86 } 87 case ISD::BUILD_VECTOR: { 88 // Select appropriate [x]vrepli.[bhwd] instructions for constant splats of 89 // 128/256-bit when LSX/LASX is enabled. 90 BuildVectorSDNode *BVN = cast<BuildVectorSDNode>(Node); 91 APInt SplatValue, SplatUndef; 92 unsigned SplatBitSize; 93 bool HasAnyUndefs; 94 unsigned Op; 95 EVT ViaVecTy; 96 bool Is128Vec = BVN->getValueType(0).is128BitVector(); 97 bool Is256Vec = BVN->getValueType(0).is256BitVector(); 98 99 if (!Subtarget->hasExtLSX() || (!Is128Vec && !Is256Vec)) 100 break; 101 if (!BVN->isConstantSplat(SplatValue, SplatUndef, SplatBitSize, 102 HasAnyUndefs, 8)) 103 break; 104 105 switch (SplatBitSize) { 106 default: 107 break; 108 case 8: 109 Op = Is256Vec ? LoongArch::PseudoXVREPLI_B : LoongArch::PseudoVREPLI_B; 110 ViaVecTy = Is256Vec ? MVT::v32i8 : MVT::v16i8; 111 break; 112 case 16: 113 Op = Is256Vec ? LoongArch::PseudoXVREPLI_H : LoongArch::PseudoVREPLI_H; 114 ViaVecTy = Is256Vec ? MVT::v16i16 : MVT::v8i16; 115 break; 116 case 32: 117 Op = Is256Vec ? LoongArch::PseudoXVREPLI_W : LoongArch::PseudoVREPLI_W; 118 ViaVecTy = Is256Vec ? MVT::v8i32 : MVT::v4i32; 119 break; 120 case 64: 121 Op = Is256Vec ? LoongArch::PseudoXVREPLI_D : LoongArch::PseudoVREPLI_D; 122 ViaVecTy = Is256Vec ? MVT::v4i64 : MVT::v2i64; 123 break; 124 } 125 126 SDNode *Res; 127 // If we have a signed 10 bit integer, we can splat it directly. 128 if (SplatValue.isSignedIntN(10)) { 129 SDValue Imm = CurDAG->getTargetConstant(SplatValue, DL, 130 ViaVecTy.getVectorElementType()); 131 Res = CurDAG->getMachineNode(Op, DL, ViaVecTy, Imm); 132 ReplaceNode(Node, Res); 133 return; 134 } 135 break; 136 } 137 } 138 139 // Select the default instruction. 140 SelectCode(Node); 141 } 142 143 bool LoongArchDAGToDAGISel::SelectInlineAsmMemoryOperand( 144 const SDValue &Op, InlineAsm::ConstraintCode ConstraintID, 145 std::vector<SDValue> &OutOps) { 146 SDValue Base = Op; 147 SDValue Offset = 148 CurDAG->getTargetConstant(0, SDLoc(Op), Subtarget->getGRLenVT()); 149 switch (ConstraintID) { 150 default: 151 llvm_unreachable("unexpected asm memory constraint"); 152 // Reg+Reg addressing. 153 case InlineAsm::ConstraintCode::k: 154 Base = Op.getOperand(0); 155 Offset = Op.getOperand(1); 156 break; 157 // Reg+simm12 addressing. 158 case InlineAsm::ConstraintCode::m: 159 if (CurDAG->isBaseWithConstantOffset(Op)) { 160 ConstantSDNode *CN = dyn_cast<ConstantSDNode>(Op.getOperand(1)); 161 if (isIntN(12, CN->getSExtValue())) { 162 Base = Op.getOperand(0); 163 Offset = CurDAG->getTargetConstant(CN->getZExtValue(), SDLoc(Op), 164 Op.getValueType()); 165 } 166 } 167 break; 168 // Reg+0 addressing. 169 case InlineAsm::ConstraintCode::ZB: 170 break; 171 // Reg+(simm14<<2) addressing. 172 case InlineAsm::ConstraintCode::ZC: 173 if (CurDAG->isBaseWithConstantOffset(Op)) { 174 ConstantSDNode *CN = dyn_cast<ConstantSDNode>(Op.getOperand(1)); 175 if (isIntN(16, CN->getSExtValue()) && 176 isAligned(Align(4ULL), CN->getZExtValue())) { 177 Base = Op.getOperand(0); 178 Offset = CurDAG->getTargetConstant(CN->getZExtValue(), SDLoc(Op), 179 Op.getValueType()); 180 } 181 } 182 break; 183 } 184 OutOps.push_back(Base); 185 OutOps.push_back(Offset); 186 return false; 187 } 188 189 bool LoongArchDAGToDAGISel::SelectBaseAddr(SDValue Addr, SDValue &Base) { 190 // If this is FrameIndex, select it directly. Otherwise just let it get 191 // selected to a register independently. 192 if (auto *FIN = dyn_cast<FrameIndexSDNode>(Addr)) 193 Base = 194 CurDAG->getTargetFrameIndex(FIN->getIndex(), Subtarget->getGRLenVT()); 195 else 196 Base = Addr; 197 return true; 198 } 199 200 // Fold constant addresses. 201 bool LoongArchDAGToDAGISel::SelectAddrConstant(SDValue Addr, SDValue &Base, 202 SDValue &Offset) { 203 SDLoc DL(Addr); 204 MVT VT = Addr.getSimpleValueType(); 205 206 if (!isa<ConstantSDNode>(Addr)) 207 return false; 208 209 // If the constant is a simm12, we can fold the whole constant and use R0 as 210 // the base. 211 int64_t CVal = cast<ConstantSDNode>(Addr)->getSExtValue(); 212 if (!isInt<12>(CVal)) 213 return false; 214 Base = CurDAG->getRegister(LoongArch::R0, VT); 215 Offset = CurDAG->getTargetConstant(SignExtend64<12>(CVal), DL, VT); 216 return true; 217 } 218 219 bool LoongArchDAGToDAGISel::selectNonFIBaseAddr(SDValue Addr, SDValue &Base) { 220 // If this is FrameIndex, don't select it. 221 if (isa<FrameIndexSDNode>(Addr)) 222 return false; 223 Base = Addr; 224 return true; 225 } 226 227 bool LoongArchDAGToDAGISel::selectShiftMask(SDValue N, unsigned ShiftWidth, 228 SDValue &ShAmt) { 229 // Shift instructions on LoongArch only read the lower 5 or 6 bits of the 230 // shift amount. If there is an AND on the shift amount, we can bypass it if 231 // it doesn't affect any of those bits. 232 if (N.getOpcode() == ISD::AND && isa<ConstantSDNode>(N.getOperand(1))) { 233 const APInt &AndMask = N->getConstantOperandAPInt(1); 234 235 // Since the max shift amount is a power of 2 we can subtract 1 to make a 236 // mask that covers the bits needed to represent all shift amounts. 237 assert(isPowerOf2_32(ShiftWidth) && "Unexpected max shift amount!"); 238 APInt ShMask(AndMask.getBitWidth(), ShiftWidth - 1); 239 240 if (ShMask.isSubsetOf(AndMask)) { 241 ShAmt = N.getOperand(0); 242 return true; 243 } 244 245 // SimplifyDemandedBits may have optimized the mask so try restoring any 246 // bits that are known zero. 247 KnownBits Known = CurDAG->computeKnownBits(N->getOperand(0)); 248 if (ShMask.isSubsetOf(AndMask | Known.Zero)) { 249 ShAmt = N.getOperand(0); 250 return true; 251 } 252 } else if (N.getOpcode() == LoongArchISD::BSTRPICK) { 253 // Similar to the above AND, if there is a BSTRPICK on the shift amount, we 254 // can bypass it. 255 assert(isPowerOf2_32(ShiftWidth) && "Unexpected max shift amount!"); 256 assert(isa<ConstantSDNode>(N.getOperand(1)) && "Illegal msb operand!"); 257 assert(isa<ConstantSDNode>(N.getOperand(2)) && "Illegal lsb operand!"); 258 uint64_t msb = N.getConstantOperandVal(1), lsb = N.getConstantOperandVal(2); 259 if (lsb == 0 && Log2_32(ShiftWidth) <= msb + 1) { 260 ShAmt = N.getOperand(0); 261 return true; 262 } 263 } else if (N.getOpcode() == ISD::SUB && 264 isa<ConstantSDNode>(N.getOperand(0))) { 265 uint64_t Imm = N.getConstantOperandVal(0); 266 // If we are shifting by N-X where N == 0 mod Size, then just shift by -X to 267 // generate a NEG instead of a SUB of a constant. 268 if (Imm != 0 && Imm % ShiftWidth == 0) { 269 SDLoc DL(N); 270 EVT VT = N.getValueType(); 271 SDValue Zero = 272 CurDAG->getCopyFromReg(CurDAG->getEntryNode(), DL, LoongArch::R0, VT); 273 unsigned NegOpc = VT == MVT::i64 ? LoongArch::SUB_D : LoongArch::SUB_W; 274 MachineSDNode *Neg = 275 CurDAG->getMachineNode(NegOpc, DL, VT, Zero, N.getOperand(1)); 276 ShAmt = SDValue(Neg, 0); 277 return true; 278 } 279 } 280 281 ShAmt = N; 282 return true; 283 } 284 285 bool LoongArchDAGToDAGISel::selectSExti32(SDValue N, SDValue &Val) { 286 if (N.getOpcode() == ISD::SIGN_EXTEND_INREG && 287 cast<VTSDNode>(N.getOperand(1))->getVT() == MVT::i32) { 288 Val = N.getOperand(0); 289 return true; 290 } 291 if (N.getOpcode() == LoongArchISD::BSTRPICK && 292 N.getConstantOperandVal(1) < UINT64_C(0X1F) && 293 N.getConstantOperandVal(2) == UINT64_C(0)) { 294 Val = N; 295 return true; 296 } 297 MVT VT = N.getSimpleValueType(); 298 if (CurDAG->ComputeNumSignBits(N) > (VT.getSizeInBits() - 32)) { 299 Val = N; 300 return true; 301 } 302 303 return false; 304 } 305 306 bool LoongArchDAGToDAGISel::selectZExti32(SDValue N, SDValue &Val) { 307 if (N.getOpcode() == ISD::AND) { 308 auto *C = dyn_cast<ConstantSDNode>(N.getOperand(1)); 309 if (C && C->getZExtValue() == UINT64_C(0xFFFFFFFF)) { 310 Val = N.getOperand(0); 311 return true; 312 } 313 } 314 MVT VT = N.getSimpleValueType(); 315 APInt Mask = APInt::getHighBitsSet(VT.getSizeInBits(), 32); 316 if (CurDAG->MaskedValueIsZero(N, Mask)) { 317 Val = N; 318 return true; 319 } 320 321 return false; 322 } 323 324 bool LoongArchDAGToDAGISel::selectVSplat(SDNode *N, APInt &Imm, 325 unsigned MinSizeInBits) const { 326 if (!Subtarget->hasExtLSX()) 327 return false; 328 329 BuildVectorSDNode *Node = dyn_cast<BuildVectorSDNode>(N); 330 331 if (!Node) 332 return false; 333 334 APInt SplatValue, SplatUndef; 335 unsigned SplatBitSize; 336 bool HasAnyUndefs; 337 338 if (!Node->isConstantSplat(SplatValue, SplatUndef, SplatBitSize, HasAnyUndefs, 339 MinSizeInBits, /*IsBigEndian=*/false)) 340 return false; 341 342 Imm = SplatValue; 343 344 return true; 345 } 346 347 template <unsigned ImmBitSize, bool IsSigned> 348 bool LoongArchDAGToDAGISel::selectVSplatImm(SDValue N, SDValue &SplatVal) { 349 APInt ImmValue; 350 EVT EltTy = N->getValueType(0).getVectorElementType(); 351 352 if (N->getOpcode() == ISD::BITCAST) 353 N = N->getOperand(0); 354 355 if (selectVSplat(N.getNode(), ImmValue, EltTy.getSizeInBits()) && 356 ImmValue.getBitWidth() == EltTy.getSizeInBits()) { 357 if (IsSigned && ImmValue.isSignedIntN(ImmBitSize)) { 358 SplatVal = CurDAG->getTargetConstant(ImmValue.getSExtValue(), SDLoc(N), 359 Subtarget->getGRLenVT()); 360 return true; 361 } 362 if (!IsSigned && ImmValue.isIntN(ImmBitSize)) { 363 SplatVal = CurDAG->getTargetConstant(ImmValue.getZExtValue(), SDLoc(N), 364 Subtarget->getGRLenVT()); 365 return true; 366 } 367 } 368 369 return false; 370 } 371 372 bool LoongArchDAGToDAGISel::selectVSplatUimmInvPow2(SDValue N, 373 SDValue &SplatImm) const { 374 APInt ImmValue; 375 EVT EltTy = N->getValueType(0).getVectorElementType(); 376 377 if (N->getOpcode() == ISD::BITCAST) 378 N = N->getOperand(0); 379 380 if (selectVSplat(N.getNode(), ImmValue, EltTy.getSizeInBits()) && 381 ImmValue.getBitWidth() == EltTy.getSizeInBits()) { 382 int32_t Log2 = (~ImmValue).exactLogBase2(); 383 384 if (Log2 != -1) { 385 SplatImm = CurDAG->getTargetConstant(Log2, SDLoc(N), EltTy); 386 return true; 387 } 388 } 389 390 return false; 391 } 392 393 bool LoongArchDAGToDAGISel::selectVSplatUimmPow2(SDValue N, 394 SDValue &SplatImm) const { 395 APInt ImmValue; 396 EVT EltTy = N->getValueType(0).getVectorElementType(); 397 398 if (N->getOpcode() == ISD::BITCAST) 399 N = N->getOperand(0); 400 401 if (selectVSplat(N.getNode(), ImmValue, EltTy.getSizeInBits()) && 402 ImmValue.getBitWidth() == EltTy.getSizeInBits()) { 403 int32_t Log2 = ImmValue.exactLogBase2(); 404 405 if (Log2 != -1) { 406 SplatImm = CurDAG->getTargetConstant(Log2, SDLoc(N), EltTy); 407 return true; 408 } 409 } 410 411 return false; 412 } 413 414 // This pass converts a legalized DAG into a LoongArch-specific DAG, ready 415 // for instruction scheduling. 416 FunctionPass *llvm::createLoongArchISelDag(LoongArchTargetMachine &TM) { 417 return new LoongArchDAGToDAGISel(TM); 418 } 419