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 19 using namespace llvm; 20 21 #define DEBUG_TYPE "loongarch-isel" 22 23 void LoongArchDAGToDAGISel::Select(SDNode *Node) { 24 // If we have a custom node, we have already selected. 25 if (Node->isMachineOpcode()) { 26 LLVM_DEBUG(dbgs() << "== "; Node->dump(CurDAG); dbgs() << "\n"); 27 Node->setNodeId(-1); 28 return; 29 } 30 31 // Instruction Selection not handled by the auto-generated tablegen selection 32 // should be handled here. 33 unsigned Opcode = Node->getOpcode(); 34 MVT GRLenVT = Subtarget->getGRLenVT(); 35 SDLoc DL(Node); 36 MVT VT = Node->getSimpleValueType(0); 37 38 switch (Opcode) { 39 default: 40 break; 41 case ISD::Constant: { 42 int64_t Imm = cast<ConstantSDNode>(Node)->getSExtValue(); 43 if (Imm == 0 && VT == GRLenVT) { 44 SDValue New = CurDAG->getCopyFromReg(CurDAG->getEntryNode(), DL, 45 LoongArch::R0, GRLenVT); 46 ReplaceNode(Node, New.getNode()); 47 return; 48 } 49 SDNode *Result = nullptr; 50 SDValue SrcReg = CurDAG->getRegister(LoongArch::R0, GRLenVT); 51 // The instructions in the sequence are handled here. 52 for (LoongArchMatInt::Inst &Inst : LoongArchMatInt::generateInstSeq(Imm)) { 53 SDValue SDImm = CurDAG->getTargetConstant(Inst.Imm, DL, GRLenVT); 54 if (Inst.Opc == LoongArch::LU12I_W) 55 Result = CurDAG->getMachineNode(LoongArch::LU12I_W, DL, GRLenVT, SDImm); 56 else 57 Result = CurDAG->getMachineNode(Inst.Opc, DL, GRLenVT, SrcReg, SDImm); 58 SrcReg = SDValue(Result, 0); 59 } 60 61 ReplaceNode(Node, Result); 62 return; 63 } 64 case ISD::FrameIndex: { 65 SDValue Imm = CurDAG->getTargetConstant(0, DL, GRLenVT); 66 int FI = cast<FrameIndexSDNode>(Node)->getIndex(); 67 SDValue TFI = CurDAG->getTargetFrameIndex(FI, VT); 68 unsigned ADDIOp = 69 Subtarget->is64Bit() ? LoongArch::ADDI_D : LoongArch::ADDI_W; 70 ReplaceNode(Node, CurDAG->getMachineNode(ADDIOp, DL, VT, TFI, Imm)); 71 return; 72 } 73 // TODO: Add selection nodes needed later. 74 } 75 76 // Select the default instruction. 77 SelectCode(Node); 78 } 79 80 bool LoongArchDAGToDAGISel::SelectBaseAddr(SDValue Addr, SDValue &Base) { 81 // If this is FrameIndex, select it directly. Otherwise just let it get 82 // selected to a register independently. 83 if (auto *FIN = dyn_cast<FrameIndexSDNode>(Addr)) 84 Base = 85 CurDAG->getTargetFrameIndex(FIN->getIndex(), Subtarget->getGRLenVT()); 86 else 87 Base = Addr; 88 return true; 89 } 90 91 bool LoongArchDAGToDAGISel::selectShiftMask(SDValue N, unsigned ShiftWidth, 92 SDValue &ShAmt) { 93 // Shift instructions on LoongArch only read the lower 5 or 6 bits of the 94 // shift amount. If there is an AND on the shift amount, we can bypass it if 95 // it doesn't affect any of those bits. 96 if (N.getOpcode() == ISD::AND && isa<ConstantSDNode>(N.getOperand(1))) { 97 const APInt &AndMask = N->getConstantOperandAPInt(1); 98 99 // Since the max shift amount is a power of 2 we can subtract 1 to make a 100 // mask that covers the bits needed to represent all shift amounts. 101 assert(isPowerOf2_32(ShiftWidth) && "Unexpected max shift amount!"); 102 APInt ShMask(AndMask.getBitWidth(), ShiftWidth - 1); 103 104 if (ShMask.isSubsetOf(AndMask)) { 105 ShAmt = N.getOperand(0); 106 return true; 107 } 108 109 // SimplifyDemandedBits may have optimized the mask so try restoring any 110 // bits that are known zero. 111 KnownBits Known = CurDAG->computeKnownBits(N->getOperand(0)); 112 if (ShMask.isSubsetOf(AndMask | Known.Zero)) { 113 ShAmt = N.getOperand(0); 114 return true; 115 } 116 } else if (N.getOpcode() == LoongArchISD::BSTRPICK) { 117 // Similar to the above AND, if there is a BSTRPICK on the shift amount, we 118 // can bypass it. 119 assert(isPowerOf2_32(ShiftWidth) && "Unexpected max shift amount!"); 120 assert(isa<ConstantSDNode>(N.getOperand(1)) && "Illegal msb operand!"); 121 assert(isa<ConstantSDNode>(N.getOperand(2)) && "Illegal lsb operand!"); 122 uint64_t msb = N.getConstantOperandVal(1), lsb = N.getConstantOperandVal(2); 123 if (lsb == 0 && Log2_32(ShiftWidth) <= msb + 1) { 124 ShAmt = N.getOperand(0); 125 return true; 126 } 127 } else if (N.getOpcode() == ISD::SUB && 128 isa<ConstantSDNode>(N.getOperand(0))) { 129 uint64_t Imm = N.getConstantOperandVal(0); 130 // If we are shifting by N-X where N == 0 mod Size, then just shift by -X to 131 // generate a NEG instead of a SUB of a constant. 132 if (Imm != 0 && Imm % ShiftWidth == 0) { 133 SDLoc DL(N); 134 EVT VT = N.getValueType(); 135 SDValue Zero = 136 CurDAG->getCopyFromReg(CurDAG->getEntryNode(), DL, LoongArch::R0, VT); 137 unsigned NegOpc = VT == MVT::i64 ? LoongArch::SUB_D : LoongArch::SUB_W; 138 MachineSDNode *Neg = 139 CurDAG->getMachineNode(NegOpc, DL, VT, Zero, N.getOperand(1)); 140 ShAmt = SDValue(Neg, 0); 141 return true; 142 } 143 } 144 145 ShAmt = N; 146 return true; 147 } 148 149 bool LoongArchDAGToDAGISel::selectSExti32(SDValue N, SDValue &Val) { 150 if (N.getOpcode() == ISD::SIGN_EXTEND_INREG && 151 cast<VTSDNode>(N.getOperand(1))->getVT() == MVT::i32) { 152 Val = N.getOperand(0); 153 return true; 154 } 155 MVT VT = N.getSimpleValueType(); 156 if (CurDAG->ComputeNumSignBits(N) > (VT.getSizeInBits() - 32)) { 157 Val = N; 158 return true; 159 } 160 161 return false; 162 } 163 164 bool LoongArchDAGToDAGISel::selectZExti32(SDValue N, SDValue &Val) { 165 if (N.getOpcode() == ISD::AND) { 166 auto *C = dyn_cast<ConstantSDNode>(N.getOperand(1)); 167 if (C && C->getZExtValue() == UINT64_C(0xFFFFFFFF)) { 168 Val = N.getOperand(0); 169 return true; 170 } 171 } 172 MVT VT = N.getSimpleValueType(); 173 APInt Mask = APInt::getHighBitsSet(VT.getSizeInBits(), 32); 174 if (CurDAG->MaskedValueIsZero(N, Mask)) { 175 Val = N; 176 return true; 177 } 178 179 return false; 180 } 181 182 // This pass converts a legalized DAG into a LoongArch-specific DAG, ready 183 // for instruction scheduling. 184 FunctionPass *llvm::createLoongArchISelDag(LoongArchTargetMachine &TM) { 185 return new LoongArchDAGToDAGISel(TM); 186 } 187