llvm-project/llvm/lib/Target/RISCV/RISCVSelectionDAGInfo.h
Sudharsan Veeravalli c9684e5892
[RISCV] Implement EmitTargetCodeForMemset for Xqcilsm (#151555)
This patch adds support for converting memset calls to one or more
`QC_SETWMI` instructions when beneficial. We only handle aligned memset
calls for now.

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
doesn't 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 number of words handled 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.
2025-08-04 12:51:14 +05:30

68 lines
2.1 KiB
C++

//===----------------------------------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_LIB_TARGET_RISCV_RISCVSELECTIONDAGINFO_H
#define LLVM_LIB_TARGET_RISCV_RISCVSELECTIONDAGINFO_H
#include "llvm/CodeGen/SDNodeInfo.h"
#include "llvm/CodeGen/SelectionDAGTargetInfo.h"
#define GET_SDNODE_ENUM
#include "RISCVGenSDNodeInfo.inc"
namespace llvm {
namespace RISCVISD {
// RISCVISD Node TSFlags
enum : llvm::SDNodeTSFlags {
HasPassthruOpMask = 1 << 0,
HasMaskOpMask = 1 << 1,
};
} // namespace RISCVISD
class RISCVSelectionDAGInfo : public SelectionDAGGenTargetInfo {
public:
RISCVSelectionDAGInfo();
~RISCVSelectionDAGInfo() override;
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;
}
bool hasMaskOp(unsigned Opcode) const {
return GenNodeInfo.getDesc(Opcode).TSFlags & RISCVISD::HasMaskOpMask;
}
unsigned getMAccOpcode(unsigned MulOpcode) const {
switch (static_cast<RISCVISD::GenNodeType>(MulOpcode)) {
default:
llvm_unreachable("Unexpected opcode");
case RISCVISD::VWMUL_VL:
return RISCVISD::VWMACC_VL;
case RISCVISD::VWMULU_VL:
return RISCVISD::VWMACCU_VL;
case RISCVISD::VWMULSU_VL:
return RISCVISD::VWMACCSU_VL;
}
}
};
} // namespace llvm
#endif // LLVM_LIB_TARGET_RISCV_RISCVSELECTIONDAGINFO_H