Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions llvm/lib/Target/RISCV/RISCVISelDAGToDAG.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1845,6 +1845,15 @@ void RISCVDAGToDAGISel::Select(SDNode *Node) {
CurDAG->RemoveDeadNode(Node);
return;
}
case RISCVISD::QC_SETWMI: {
SDValue Chain = Node->getOperand(0);
SDVTList VTs = Node->getVTList();
SDValue Ops[] = {Node->getOperand(1), Node->getOperand(2),
Node->getOperand(3), Node->getOperand(4), Chain};
MachineSDNode *New = CurDAG->getMachineNode(RISCV::QC_SETWMI, DL, VTs, Ops);
ReplaceNode(Node, New);
return;
}
case ISD::INTRINSIC_WO_CHAIN: {
unsigned IntNo = Node->getConstantOperandVal(0);
switch (IntNo) {
Expand Down
8 changes: 8 additions & 0 deletions llvm/lib/Target/RISCV/RISCVInstrInfoXqci.td
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,14 @@
// Operand and SDNode transformation definitions.
//===----------------------------------------------------------------------===//

def SDT_StoreMultiple : SDTypeProfile<0, 4, [SDTCisSameAs<0, 1>,
SDTCisSameAs<1, 3>,
SDTCisPtrTy<2>,
SDTCisVT<3, XLenVT>]>;

def qc_setwmi : RVSDNode<"QC_SETWMI", SDT_StoreMultiple,
[SDNPHasChain, SDNPMayStore, SDNPMemOperand]>;

def uimm5nonzero : RISCVOp<XLenVT>,
ImmLeaf<XLenVT, [{return (Imm != 0) && isUInt<5>(Imm);}]> {
let ParserMatchClass = UImmAsmOperand<5, "NonZero">;
Expand Down
101 changes: 101 additions & 0 deletions llvm/lib/Target/RISCV/RISCVSelectionDAGInfo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@
//===----------------------------------------------------------------------===//

#include "RISCVSelectionDAGInfo.h"
#include "RISCVSubtarget.h"
#include "llvm/CodeGen/SelectionDAG.h"

#define GET_SDNODE_DESC
#include "RISCVGenSDNodeInfo.inc"
Expand Down Expand Up @@ -62,3 +64,102 @@ void RISCVSelectionDAGInfo::verifyTargetNode(const SelectionDAG &DAG,
}
#endif
}

SDValue RISCVSelectionDAGInfo::EmitTargetCodeForMemset(
SelectionDAG &DAG, const SDLoc &dl, SDValue Chain, SDValue Dst, SDValue Src,
SDValue Size, Align Alignment, bool isVolatile, bool AlwaysInline,
MachinePointerInfo DstPtrInfo) const {
const RISCVSubtarget &Subtarget =
DAG.getMachineFunction().getSubtarget<RISCVSubtarget>();
// We currently do this only for Xqcilsm
if (!Subtarget.hasVendorXqcilsm())
return SDValue();

// Do this only if we know the size at compile time.
ConstantSDNode *ConstantSize = dyn_cast<ConstantSDNode>(Size);
if (!ConstantSize)
return SDValue();

uint64_t NumberOfBytesToWrite = ConstantSize->getZExtValue();

// Do this only if it is word aligned and we write multiple of 4 bytes.
if (!((Alignment.value() & 3) == 0 && (NumberOfBytesToWrite & 3) == 0))
return SDValue();

SmallVector<SDValue, 8> OutChains;
SDValue SizeWords, OffsetSetwmi;
SDValue SrcValueReplicated = DAG.getNode(ISD::ZERO_EXTEND, dl, MVT::i32, Src);
int NumberOfWords = NumberOfBytesToWrite / 4;

// Helper for constructing the QC_SETWMI instruction
auto getSetwmiNode = [&](SDValue SizeWords, SDValue OffsetSetwmi) -> SDValue {
SDValue Ops[] = {Chain, SrcValueReplicated, Dst, SizeWords, OffsetSetwmi};
return DAG.getNode(RISCVISD::QC_SETWMI, dl, MVT::Other, Ops);
};

bool IsZeroVal =
isa<ConstantSDNode>(Src) && cast<ConstantSDNode>(Src)->isZero();

// If i8 type and constant non-zero value.
if ((Src.getValueType() == MVT::i8) && !IsZeroVal)
// Replicate byte to word by multiplication with 0x01010101.
SrcValueReplicated = DAG.getNode(ISD::MUL, dl, MVT::i32, SrcValueReplicated,
DAG.getConstant(16843009, dl, MVT::i32));

// We limit a QC_SETWMI to 16 words or less to improve interruptibility.
// So for 1-16 words we use a single QC_SETWMI:
//
// QC_SETWMI reg1, N, 0(reg2)
//
// For 17-32 words we use two QC_SETWMI's with the first as 16 words and the
// second for the remainder:
//
// QC_SETWMI reg1, 16, 0(reg2)
// QC_SETWMI reg1, N, 64(reg2)
//
// For 33-48 words, we would like to use (16, 16, n), but that means the last
// QC_SETWMI needs an offset of 128 which the instruction doesnt support.
// So in this case we use a length of 15 for the second instruction and we do
// the rest with the third instruction.
// This means the maximum inlined number of words is 47 (for now):
//
// QC_SETWMI R2, R0, 16, 0
// QC_SETWMI R2, R0, 15, 64
// QC_SETWMI R2, R0, N, 124
//
// For 48 words or more, call the target independent memset
if (NumberOfWords <= 16) {
// 1 - 16 words
SizeWords = DAG.getTargetConstant(NumberOfWords, dl, MVT::i32);
SDValue OffsetSetwmi = DAG.getTargetConstant(0, dl, MVT::i32);
return getSetwmiNode(SizeWords, OffsetSetwmi);
} else if (NumberOfWords <= 47) {
if (NumberOfWords <= 32) {
// 17 - 32 words
SizeWords = DAG.getTargetConstant(NumberOfWords - 16, dl, MVT::i32);
OffsetSetwmi = DAG.getTargetConstant(64, dl, MVT::i32);
OutChains.push_back(getSetwmiNode(SizeWords, OffsetSetwmi));

SizeWords = DAG.getTargetConstant(16, dl, MVT::i32);
OffsetSetwmi = DAG.getTargetConstant(0, dl, MVT::i32);
OutChains.push_back(getSetwmiNode(SizeWords, OffsetSetwmi));
} else {
// 33 - 47 words
SizeWords = DAG.getTargetConstant(NumberOfWords - 31, dl, MVT::i32);
OffsetSetwmi = DAG.getTargetConstant(124, dl, MVT::i32);
OutChains.push_back(getSetwmiNode(SizeWords, OffsetSetwmi));

SizeWords = DAG.getTargetConstant(15, dl, MVT::i32);
OffsetSetwmi = DAG.getTargetConstant(64, dl, MVT::i32);
OutChains.push_back(getSetwmiNode(SizeWords, OffsetSetwmi));

SizeWords = DAG.getTargetConstant(16, dl, MVT::i32);
OffsetSetwmi = DAG.getTargetConstant(0, dl, MVT::i32);
OutChains.push_back(getSetwmiNode(SizeWords, OffsetSetwmi));
}
return DAG.getNode(ISD::TokenFactor, dl, MVT::Other, OutChains);
}

// >= 48 words. Call target independent memset.
return SDValue();
}
6 changes: 6 additions & 0 deletions llvm/lib/Target/RISCV/RISCVSelectionDAGInfo.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,12 @@ class RISCVSelectionDAGInfo : public SelectionDAGGenTargetInfo {
void verifyTargetNode(const SelectionDAG &DAG,
const SDNode *N) const override;

SDValue EmitTargetCodeForMemset(SelectionDAG &DAG, const SDLoc &dl,
SDValue Chain, SDValue Dst, SDValue Src,
SDValue Size, Align Alignment,
bool isVolatile, bool AlwaysInline,
MachinePointerInfo DstPtrInfo) const override;

bool hasPassthruOp(unsigned Opcode) const {
return GenNodeInfo.getDesc(Opcode).TSFlags & RISCVISD::HasPassthruOpMask;
}
Expand Down
Loading