LoongArchISelDAGToDAG.cpp 8.5 KB

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