149 lines · cpp
1//===----------------------------------------------------------------------===//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-exception6//7//===----------------------------------------------------------------------===//8 9#include "RISCVSelectionDAGInfo.h"10#include "RISCVSubtarget.h"11#include "llvm/CodeGen/SelectionDAG.h"12 13#define GET_SDNODE_DESC14#include "RISCVGenSDNodeInfo.inc"15 16using namespace llvm;17 18RISCVSelectionDAGInfo::RISCVSelectionDAGInfo()19 : SelectionDAGGenTargetInfo(RISCVGenSDNodeInfo) {}20 21RISCVSelectionDAGInfo::~RISCVSelectionDAGInfo() = default;22 23void RISCVSelectionDAGInfo::verifyTargetNode(const SelectionDAG &DAG,24 const SDNode *N) const {25 SelectionDAGGenTargetInfo::verifyTargetNode(DAG, N);26 27#ifndef NDEBUG28 // Some additional checks not yet implemented by verifyTargetNode.29 switch (N->getOpcode()) {30 case RISCVISD::TUPLE_EXTRACT:31 assert(N->getOperand(1).getOpcode() == ISD::TargetConstant &&32 "Expected index to be a target constant!");33 break;34 case RISCVISD::TUPLE_INSERT:35 assert(N->getOperand(2).getOpcode() == ISD::TargetConstant &&36 "Expected index to be a target constant!");37 break;38 case RISCVISD::VQDOT_VL:39 case RISCVISD::VQDOTU_VL:40 case RISCVISD::VQDOTSU_VL: {41 EVT VT = N->getValueType(0);42 assert(VT.isScalableVector() && VT.getVectorElementType() == MVT::i32 &&43 "Expected result to be an i32 scalable vector");44 assert(N->getOperand(0).getValueType() == VT &&45 N->getOperand(1).getValueType() == VT &&46 N->getOperand(2).getValueType() == VT &&47 "Expected result and first 3 operands to have the same type!");48 EVT MaskVT = N->getOperand(3).getValueType();49 assert(MaskVT.isScalableVector() &&50 MaskVT.getVectorElementCount() == VT.getVectorElementCount() &&51 "Expected mask VT to be an i1 scalable vector with same number of "52 "elements as the result");53 break;54 }55 }56#endif57}58 59SDValue RISCVSelectionDAGInfo::EmitTargetCodeForMemset(60 SelectionDAG &DAG, const SDLoc &dl, SDValue Chain, SDValue Dst, SDValue Src,61 SDValue Size, Align Alignment, bool isVolatile, bool AlwaysInline,62 MachinePointerInfo DstPtrInfo) const {63 const auto &Subtarget = DAG.getSubtarget<RISCVSubtarget>();64 // We currently do this only for Xqcilsm65 if (!Subtarget.hasVendorXqcilsm())66 return SDValue();67 68 // Do this only if we know the size at compile time.69 ConstantSDNode *ConstantSize = dyn_cast<ConstantSDNode>(Size);70 if (!ConstantSize)71 return SDValue();72 73 uint64_t NumberOfBytesToWrite = ConstantSize->getZExtValue();74 75 // Do this only if it is word aligned and we write a multiple of 4 bytes.76 if (!(Alignment >= 4) || !((NumberOfBytesToWrite & 3) == 0))77 return SDValue();78 79 SmallVector<SDValue, 8> OutChains;80 SDValue SrcValueReplicated = DAG.getNode(ISD::ZERO_EXTEND, dl, MVT::i32, Src);81 int NumberOfWords = NumberOfBytesToWrite / 4;82 MachineFunction &MF = DAG.getMachineFunction();83 auto Volatile =84 isVolatile ? MachineMemOperand::MOVolatile : MachineMemOperand::MONone;85 86 // Helper for constructing the QC_SETWMI instruction87 auto getSetwmiNode = [&](uint8_t SizeWords, uint8_t OffsetSetwmi) -> SDValue {88 SDValue Ops[] = {Chain, SrcValueReplicated, Dst,89 DAG.getTargetConstant(SizeWords, dl, MVT::i32),90 DAG.getTargetConstant(OffsetSetwmi, dl, MVT::i32)};91 MachineMemOperand *BaseMemOperand = MF.getMachineMemOperand(92 DstPtrInfo.getWithOffset(OffsetSetwmi),93 MachineMemOperand::MOStore | Volatile, SizeWords * 4, Align(4));94 return DAG.getMemIntrinsicNode(RISCVISD::QC_SETWMI, dl,95 DAG.getVTList(MVT::Other), Ops, MVT::i32,96 BaseMemOperand);97 };98 99 // If i8 type and constant non-zero value.100 if ((Src.getValueType() == MVT::i8) && !isNullConstant(Src))101 // Replicate byte to word by multiplication with 0x01010101.102 SrcValueReplicated =103 DAG.getNode(ISD::MUL, dl, MVT::i32, SrcValueReplicated,104 DAG.getConstant(0x01010101ul, dl, MVT::i32));105 106 // We limit a QC_SETWMI to 16 words or less to improve interruptibility.107 // So for 1-16 words we use a single QC_SETWMI:108 //109 // QC_SETWMI reg1, N, 0(reg2)110 //111 // For 17-32 words we use two QC_SETWMI's with the first as 16 words and the112 // second for the remainder:113 //114 // QC_SETWMI reg1, 16, 0(reg2)115 // QC_SETWMI reg1, N, 64(reg2)116 //117 // For 33-48 words, we would like to use (16, 16, n), but that means the last118 // QC_SETWMI needs an offset of 128 which the instruction doesn't support.119 // So in this case we use a length of 15 for the second instruction and we do120 // the rest with the third instruction.121 // This means the maximum inlined number of words is 47 (for now):122 //123 // QC_SETWMI R2, R0, 16, 0124 // QC_SETWMI R2, R0, 15, 64125 // QC_SETWMI R2, R0, N, 124126 //127 // For 48 words or more, call the target independent memset128 if (NumberOfWords >= 48)129 return SDValue();130 131 if (NumberOfWords <= 16) {132 // 1 - 16 words133 return getSetwmiNode(NumberOfWords, 0);134 }135 136 if (NumberOfWords <= 32) {137 // 17 - 32 words138 OutChains.push_back(getSetwmiNode(NumberOfWords - 16, 64));139 OutChains.push_back(getSetwmiNode(16, 0));140 } else {141 // 33 - 47 words142 OutChains.push_back(getSetwmiNode(NumberOfWords - 31, 124));143 OutChains.push_back(getSetwmiNode(15, 64));144 OutChains.push_back(getSetwmiNode(16, 0));145 }146 147 return DAG.getNode(ISD::TokenFactor, dl, MVT::Other, OutChains);148}149