Skip to content
Merged
Show file tree
Hide file tree
Changes from 7 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
17 changes: 17 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_SetMultiple : SDTypeProfile<0, 4, [SDTCisSameAs<0, 1>,
SDTCisSameAs<1, 3>,
SDTCisPtrTy<2>,
SDTCisVT<3, XLenVT>]>;

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

def uimm5nonzero : RISCVOp<XLenVT>,
ImmLeaf<XLenVT, [{return (Imm != 0) && isUInt<5>(Imm);}]> {
let ParserMatchClass = UImmAsmOperand<5, "NonZero">;
Expand All @@ -27,6 +35,8 @@ def uimm5nonzero : RISCVOp<XLenVT>,
}];
}

def tuimm5nonzero : TImmLeaf<XLenVT, [{return (Imm != 0) && isUInt<5>(Imm);}]>;

def uimm5gt3 : RISCVOp<XLenVT>, ImmLeaf<XLenVT,
[{return (Imm > 3) && isUInt<5>(Imm);}]> {
let ParserMatchClass = UImmAsmOperand<5, "GT3">;
Expand Down Expand Up @@ -92,6 +102,8 @@ def uimm5slist : RISCVOp<XLenVT>, ImmLeaf<XLenVT,
}];
}

def tuimm7_lsb00 : TImmLeaf<XLenVT,[{return isShiftedUInt<5, 2>(Imm);}]>;

def uimm10 : RISCVUImmLeafOp<10>;

def uimm11 : RISCVUImmLeafOp<11>;
Expand Down Expand Up @@ -1566,6 +1578,11 @@ def : QCISELECTIICCPat <SETEQ, QC_SELECTIIEQ>;
def : QCISELECTIICCPat <SETNE, QC_SELECTIINE>;
} // Predicates = [HasVendorXqcics, IsRV32]

let Predicates = [HasVendorXqcilsm, IsRV32] in {
def : Pat<(qc_setwmi GPR:$rs3, GPR:$rs1, tuimm5nonzero:$uimm5, tuimm7_lsb00:$uimm7),
(QC_SETWMI GPR:$rs3, GPR:$rs1, tuimm5nonzero:$uimm5, tuimm7_lsb00:$uimm7)>;
} // Predicates = [HasVendorXqcilsm, IsRV32]

//===----------------------------------------------------------------------===/i
// Compress Instruction tablegen backend.
//===----------------------------------------------------------------------===//
Expand Down
90 changes: 90 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,91 @@ 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 auto &Subtarget = DAG.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 >= 4) || !((NumberOfBytesToWrite & 3) == 0))
return SDValue();

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

// Helper for constructing the QC_SETWMI instruction
auto getSetwmiNode = [&](uint8_t SizeWords, uint8_t OffsetSetwmi) -> SDValue {
SDValue Ops[] = {Chain, SrcValueReplicated, Dst,
DAG.getTargetConstant(SizeWords, dl, MVT::i32),
DAG.getTargetConstant(OffsetSetwmi, dl, MVT::i32)};
MachineMemOperand *BaseMemOperand = MF.getMachineMemOperand(
DstPtrInfo, MachineMemOperand::MOStore, SizeWords * 4, Align(4));
return DAG.getMemIntrinsicNode(RISCVISD::QC_SETWMI, dl,
DAG.getVTList(MVT::Other), Ops, MVT::i32,
BaseMemOperand);
};

// If i8 type and constant non-zero value.
if ((Src.getValueType() == MVT::i8) && !isNullConstant(Src))
// Replicate byte to word by multiplication with 0x01010101.
SrcValueReplicated =
DAG.getNode(ISD::MUL, dl, MVT::i32, SrcValueReplicated,
DAG.getConstant(0x01010101ul, 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 >= 48)
return SDValue();

if (NumberOfWords <= 16) {
// 1 - 16 words
return getSetwmiNode(NumberOfWords, 0);
}

if (NumberOfWords <= 32) {
// 17 - 32 words
OutChains.push_back(getSetwmiNode(NumberOfWords - 16, 64));
OutChains.push_back(getSetwmiNode(16, 0));
} else {
// 33 - 47 words
OutChains.push_back(getSetwmiNode(NumberOfWords - 31, 124));
OutChains.push_back(getSetwmiNode(15, 64));
OutChains.push_back(getSetwmiNode(16, 0));
}

return DAG.getNode(ISD::TokenFactor, dl, MVT::Other, OutChains);
}
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