[llvm] [LoongArch] Add generation support for `preld` instruction (PR #118436)
via llvm-commits
llvm-commits at lists.llvm.org
Mon Dec 2 23:11:25 PST 2024
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-backend-loongarch
Author: ZhaoQi (zhaoqi5)
<details>
<summary>Changes</summary>
Instruction `preld` is used to prefetch one cache-line of data from memory in advance into the cache.
This commit allows it to be generated automatically.
---
Full diff: https://github.com/llvm/llvm-project/pull/118436.diff
5 Files Affected:
- (modified) llvm/lib/Target/LoongArch/LoongArchISelDAGToDAG.cpp (+22)
- (modified) llvm/lib/Target/LoongArch/LoongArchISelDAGToDAG.h (+1)
- (modified) llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp (+2)
- (modified) llvm/lib/Target/LoongArch/LoongArchInstrInfo.td (+9)
- (added) llvm/test/CodeGen/LoongArch/preld.ll (+67)
``````````diff
diff --git a/llvm/lib/Target/LoongArch/LoongArchISelDAGToDAG.cpp b/llvm/lib/Target/LoongArch/LoongArchISelDAGToDAG.cpp
index d330f953556018..099ce54cead140 100644
--- a/llvm/lib/Target/LoongArch/LoongArchISelDAGToDAG.cpp
+++ b/llvm/lib/Target/LoongArch/LoongArchISelDAGToDAG.cpp
@@ -245,6 +245,28 @@ bool LoongArchDAGToDAGISel::selectNonFIBaseAddr(SDValue Addr, SDValue &Base) {
return true;
}
+bool LoongArchDAGToDAGISel::SelectAddrRegImm(SDValue Addr, SDValue &Base,
+ SDValue &Offset) {
+ SDLoc DL(Addr);
+ MVT VT = Addr.getSimpleValueType();
+
+ // The address is the result of an ADD. Here we only consider reg+simm12.
+ if (CurDAG->isBaseWithConstantOffset(Addr)) {
+ int64_t Imm = cast<ConstantSDNode>(Addr.getOperand(1))->getSExtValue();
+ if (isInt<12>(Imm)) {
+ Base = Addr.getOperand(0);
+ Offset = CurDAG->getTargetConstant(SignExtend64<12>(Imm), DL, VT);
+ return true;
+ }
+ }
+
+ // Otherwise, we assume Addr as the base address and use constant 0 as the
+ // offset.
+ Base = Addr;
+ Offset = CurDAG->getTargetConstant(0, DL, VT);
+ return true;
+}
+
bool LoongArchDAGToDAGISel::selectShiftMask(SDValue N, unsigned ShiftWidth,
SDValue &ShAmt) {
// Shift instructions on LoongArch only read the lower 5 or 6 bits of the
diff --git a/llvm/lib/Target/LoongArch/LoongArchISelDAGToDAG.h b/llvm/lib/Target/LoongArch/LoongArchISelDAGToDAG.h
index 363b4f0ca7cf06..46c286bdb4eb77 100644
--- a/llvm/lib/Target/LoongArch/LoongArchISelDAGToDAG.h
+++ b/llvm/lib/Target/LoongArch/LoongArchISelDAGToDAG.h
@@ -43,6 +43,7 @@ class LoongArchDAGToDAGISel : public SelectionDAGISel {
bool SelectBaseAddr(SDValue Addr, SDValue &Base);
bool SelectAddrConstant(SDValue Addr, SDValue &Base, SDValue &Offset);
bool selectNonFIBaseAddr(SDValue Addr, SDValue &Base);
+ bool SelectAddrRegImm(SDValue Addr, SDValue &Base, SDValue &Offset);
bool selectShiftMask(SDValue N, unsigned ShiftWidth, SDValue &ShAmt);
bool selectShiftMaskGRLen(SDValue N, SDValue &ShAmt) {
diff --git a/llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp b/llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp
index 16bceacfaa222c..a92142a3930f0f 100644
--- a/llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp
+++ b/llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp
@@ -99,6 +99,8 @@ LoongArchTargetLowering::LoongArchTargetLowering(const TargetMachine &TM,
setOperationAction(ISD::INTRINSIC_W_CHAIN, MVT::Other, Custom);
setOperationAction(ISD::INTRINSIC_WO_CHAIN, MVT::Other, Custom);
+ setOperationAction(ISD::PREFETCH, MVT::Other, Legal);
+
// Expand bitreverse.i16 with native-width bitrev and shift for now, before
// we get to know which of sll and revb.2h is faster.
setOperationAction(ISD::BITREVERSE, MVT::i8, Custom);
diff --git a/llvm/lib/Target/LoongArch/LoongArchInstrInfo.td b/llvm/lib/Target/LoongArch/LoongArchInstrInfo.td
index 6134daf2fbe630..5eda3bc7225e05 100644
--- a/llvm/lib/Target/LoongArch/LoongArchInstrInfo.td
+++ b/llvm/lib/Target/LoongArch/LoongArchInstrInfo.td
@@ -521,6 +521,7 @@ def HI16ForAddu16idAddiPair: SDNodeXForm<imm, [{
def BaseAddr : ComplexPattern<iPTR, 1, "SelectBaseAddr">;
def AddrConstant : ComplexPattern<iPTR, 2, "SelectAddrConstant">;
def NonFIBaseAddr : ComplexPattern<iPTR, 1, "selectNonFIBaseAddr">;
+def AddrRegImm : ComplexPattern<iPTR, 2, "SelectAddrRegImm">;
def fma_nsz : PatFrag<(ops node:$fj, node:$fk, node:$fa),
(fma node:$fj, node:$fk, node:$fa), [{
@@ -2009,6 +2010,14 @@ class PseudoMaskedAMMinMax
def PseudoMaskedAtomicLoadMax32 : PseudoMaskedAMMinMax;
def PseudoMaskedAtomicLoadMin32 : PseudoMaskedAMMinMax;
+// Data prefetch
+
+// TODO: Supports for preldx instruction.
+def : Pat<(prefetch (AddrRegImm GPR:$rj, simm12:$imm12), (i32 0), timm, (i32 1)),
+ (PRELD 0, GPR:$rj, simm12:$imm12)>; // data prefetch for loads
+def : Pat<(prefetch (AddrRegImm GPR:$rj, simm12:$imm12), (i32 1), timm, (i32 1)),
+ (PRELD 8, GPR:$rj, simm12:$imm12)>; // data prefetch for stores
+
/// Compare and exchange
class PseudoCmpXchg
diff --git a/llvm/test/CodeGen/LoongArch/preld.ll b/llvm/test/CodeGen/LoongArch/preld.ll
new file mode 100644
index 00000000000000..18057ac871f753
--- /dev/null
+++ b/llvm/test/CodeGen/LoongArch/preld.ll
@@ -0,0 +1,67 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 5
+; RUN: llc --mtriple=loongarch32 < %s | FileCheck %s --check-prefix=LA32
+; RUN: llc --mtriple=loongarch64 < %s | FileCheck %s --check-prefix=LA64
+
+declare void @llvm.prefetch(ptr, i32, i32, i32)
+
+define void @load_prefetch_no_offset(ptr %a) {
+; LA32-LABEL: load_prefetch_no_offset:
+; LA32: # %bb.0: # %entry
+; LA32-NEXT: preld 0, $a0, 0
+; LA32-NEXT: ret
+;
+; LA64-LABEL: load_prefetch_no_offset:
+; LA64: # %bb.0: # %entry
+; LA64-NEXT: preld 0, $a0, 0
+; LA64-NEXT: ret
+entry:
+ call void @llvm.prefetch(ptr %a, i32 0, i32 3, i32 1)
+ ret void
+}
+
+define void @store_prefetch_no_offset(ptr %a) {
+; LA32-LABEL: store_prefetch_no_offset:
+; LA32: # %bb.0: # %entry
+; LA32-NEXT: preld 8, $a0, 0
+; LA32-NEXT: ret
+;
+; LA64-LABEL: store_prefetch_no_offset:
+; LA64: # %bb.0: # %entry
+; LA64-NEXT: preld 8, $a0, 0
+; LA64-NEXT: ret
+entry:
+ call void @llvm.prefetch(ptr %a, i32 1, i32 3, i32 1)
+ ret void
+}
+
+define void @load_prefetch_with_offset(ptr %a) {
+; LA32-LABEL: load_prefetch_with_offset:
+; LA32: # %bb.0: # %entry
+; LA32-NEXT: preld 0, $a0, 200
+; LA32-NEXT: ret
+;
+; LA64-LABEL: load_prefetch_with_offset:
+; LA64: # %bb.0: # %entry
+; LA64-NEXT: preld 0, $a0, 200
+; LA64-NEXT: ret
+entry:
+ %addr = getelementptr i8, ptr %a, i64 200
+ call void @llvm.prefetch(ptr %addr, i32 0, i32 3, i32 1)
+ ret void
+}
+
+define void @store_prefetch_with_offset(ptr %a) {
+; LA32-LABEL: store_prefetch_with_offset:
+; LA32: # %bb.0: # %entry
+; LA32-NEXT: preld 8, $a0, 200
+; LA32-NEXT: ret
+;
+; LA64-LABEL: store_prefetch_with_offset:
+; LA64: # %bb.0: # %entry
+; LA64-NEXT: preld 8, $a0, 200
+; LA64-NEXT: ret
+entry:
+ %addr = getelementptr i8, ptr %a, i64 200
+ call void @llvm.prefetch(ptr %addr, i32 1, i32 3, i32 1)
+ ret void
+}
``````````
</details>
https://github.com/llvm/llvm-project/pull/118436
More information about the llvm-commits
mailing list