[llvm] [RISCV] Initial support for EarlyCSE (PR #138812)
via llvm-commits
llvm-commits at lists.llvm.org
Wed May 7 00:35:32 PDT 2025
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-llvm-transforms
Author: Hank Chang (HankChang736)
<details>
<summary>Changes</summary>
This patch initially supports EarlyCSE for RISCV.
Note:
* Add two TTI hook `getTgtMemIntrinsic` and `getOrCreateResultFromMemIntrinsic`
* Add one test case intrinsics.ll in llvm/test/Transforms/EarlyCSE/RISCV/
---
Full diff: https://github.com/llvm/llvm-project/pull/138812.diff
3 Files Affected:
- (modified) llvm/lib/Target/RISCV/RISCVTargetTransformInfo.cpp (+45)
- (modified) llvm/lib/Target/RISCV/RISCVTargetTransformInfo.h (+8-1)
- (added) llvm/test/Transforms/EarlyCSE/RISCV/intrinsics.ll (+42)
``````````diff
diff --git a/llvm/lib/Target/RISCV/RISCVTargetTransformInfo.cpp b/llvm/lib/Target/RISCV/RISCVTargetTransformInfo.cpp
index db2f1141ee4b7..0d7fa63f33999 100644
--- a/llvm/lib/Target/RISCV/RISCVTargetTransformInfo.cpp
+++ b/llvm/lib/Target/RISCV/RISCVTargetTransformInfo.cpp
@@ -15,6 +15,7 @@
#include "llvm/CodeGen/TargetLowering.h"
#include "llvm/CodeGen/ValueTypes.h"
#include "llvm/IR/Instructions.h"
+#include "llvm/IR/IntrinsicsRISCV.h"
#include "llvm/IR/PatternMatch.h"
#include <cmath>
#include <optional>
@@ -116,6 +117,50 @@ RISCVTTIImpl::getRISCVInstructionCost(ArrayRef<unsigned> OpCodes, MVT VT,
return Cost;
}
+Value *
+RISCVTTIImpl::getOrCreateResultFromMemIntrinsic(IntrinsicInst *Inst,
+ Type *ExpectedType) const {
+ Intrinsic::ID IID = Inst->getIntrinsicID();
+ switch (IID) {
+ default:
+ return nullptr;
+ // TODO: Add more memory intrinsic operations.
+ case Intrinsic::riscv_vle: {
+ if (Inst->getType() == ExpectedType)
+ return Inst;
+ }
+ return nullptr;
+ }
+}
+
+bool RISCVTTIImpl::getTgtMemIntrinsic(IntrinsicInst *Inst,
+ MemIntrinsicInfo &Info) const {
+ Intrinsic::ID IID = Inst->getIntrinsicID();
+ switch (IID) {
+ default:
+ return false;
+ case Intrinsic::riscv_vle: {
+ // Intrinsic interface:
+ // riscv_vle(merge, ptr, vl)
+ Info.ReadMem = true;
+ Info.WriteMem = false;
+ Info.PtrVal = Inst->getArgOperand(1);
+ Info.MatchingId = VECTOR_VLE_VSE;
+ break;
+ }
+ case Intrinsic::riscv_vse: {
+ // Intrinsic interface:
+ // riscv_vse(val, ptr, vl)
+ Info.ReadMem = false;
+ Info.WriteMem = true;
+ Info.PtrVal = Inst->getArgOperand(1);
+ Info.MatchingId = VECTOR_VLE_VSE;
+ break;
+ }
+ }
+ return true;
+}
+
static InstructionCost getIntImmCostImpl(const DataLayout &DL,
const RISCVSubtarget *ST,
const APInt &Imm, Type *Ty,
diff --git a/llvm/lib/Target/RISCV/RISCVTargetTransformInfo.h b/llvm/lib/Target/RISCV/RISCVTargetTransformInfo.h
index 53529d077fd54..0eb2a033da9fb 100644
--- a/llvm/lib/Target/RISCV/RISCVTargetTransformInfo.h
+++ b/llvm/lib/Target/RISCV/RISCVTargetTransformInfo.h
@@ -37,6 +37,8 @@ class RISCVTTIImpl : public BasicTTIImplBase<RISCVTTIImpl> {
const RISCVSubtarget *getST() const { return ST; }
const RISCVTargetLowering *getTLI() const { return TLI; }
+ enum MemIntrinsicType { VECTOR_VLE_VSE };
+
/// This function returns an estimate for VL to be used in VL based terms
/// of the cost model. For fixed length vectors, this is simply the
/// vector length. For scalable vectors, we return results consistent
@@ -156,7 +158,12 @@ class RISCVTTIImpl : public BasicTTIImplBase<RISCVTTIImpl> {
void getPeelingPreferences(Loop *L, ScalarEvolution &SE,
TTI::PeelingPreferences &PP) const override;
- unsigned getMinVectorRegisterBitWidth() const override {
+ Value *getOrCreateResultFromMemIntrinsic(IntrinsicInst *Inst,
+ Type *ExpectedType) const override;
+
+ bool getTgtMemIntrinsic(IntrinsicInst *Inst, MemIntrinsicInfo &Info) const;
+
+ unsigned getMinVectorRegisterBitWidth() const {
return ST->useRVVForFixedLengthVectors() ? 16 : 0;
}
diff --git a/llvm/test/Transforms/EarlyCSE/RISCV/intrinsics.ll b/llvm/test/Transforms/EarlyCSE/RISCV/intrinsics.ll
new file mode 100644
index 0000000000000..c00e822da3de4
--- /dev/null
+++ b/llvm/test/Transforms/EarlyCSE/RISCV/intrinsics.ll
@@ -0,0 +1,42 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 5
+; RUN: opt < %s -S -mtriple=riscv64 -mattr=+v -passes=early-cse -earlycse-debug-hash | FileCheck %s
+; RUN: opt < %s -S -mtriple=riscv64 -mattr=+v -aa-pipeline=basic-aa -passes='early-cse<memssa>' | FileCheck %s
+
+define <vscale x 2 x i32> @test_cse(ptr noundef %base) {
+; CHECK-LABEL: define <vscale x 2 x i32> @test_cse(
+; CHECK-SAME: ptr noundef [[BASE:%.*]]) #[[ATTR0:[0-9]+]] {
+; CHECK-NEXT: [[ENTRY:.*:]]
+; CHECK-NEXT: [[TMP0:%.*]] = call <vscale x 2 x i32> @llvm.riscv.vle.nxv2i32.i64(<vscale x 2 x i32> poison, ptr [[BASE]], i64 8)
+; CHECK-NEXT: [[TMP1:%.*]] = call <vscale x 2 x i32> @llvm.riscv.vadd.nxv2i32.nxv2i32.i64(<vscale x 2 x i32> poison, <vscale x 2 x i32> [[TMP0]], <vscale x 2 x i32> [[TMP0]], i64 8)
+; CHECK-NEXT: ret <vscale x 2 x i32> [[TMP1]]
+;
+entry:
+ %0 = call <vscale x 2 x i32> @llvm.riscv.vle.nxv2i32.i64(<vscale x 2 x i32> poison, ptr %base, i64 8)
+ %1 = call <vscale x 2 x i32> @llvm.riscv.vle.nxv2i32.i64(<vscale x 2 x i32> poison, ptr %base, i64 8)
+ %2 = call <vscale x 2 x i32> @llvm.riscv.vadd.nxv2i32.nxv2i32.i64(<vscale x 2 x i32> poison, <vscale x 2 x i32> %0, <vscale x 2 x i32> %1, i64 8)
+ ret <vscale x 2 x i32> %2
+}
+
+define <vscale x 2 x i32> @test_no_cse(ptr noundef %a, ptr noundef %b) {
+; CHECK-LABEL: define <vscale x 2 x i32> @test_no_cse(
+; CHECK-SAME: ptr noundef [[A:%.*]], ptr noundef [[B:%.*]]) #[[ATTR0]] {
+; CHECK-NEXT: [[ENTRY:.*:]]
+; CHECK-NEXT: [[TMP0:%.*]] = call <vscale x 2 x i32> @llvm.riscv.vle.nxv2i32.i64(<vscale x 2 x i32> poison, ptr [[A]], i64 8)
+; CHECK-NEXT: [[TMP1:%.*]] = call <vscale x 2 x i32> @llvm.riscv.vle.nxv2i32.i64(<vscale x 2 x i32> poison, ptr [[B]], i64 8)
+; CHECK-NEXT: [[TMP2:%.*]] = call <vscale x 2 x i32> @llvm.riscv.vadd.nxv2i32.nxv2i32.i64(<vscale x 2 x i32> poison, <vscale x 2 x i32> [[TMP0]], <vscale x 2 x i32> [[TMP1]], i64 8)
+; CHECK-NEXT: ret <vscale x 2 x i32> [[TMP2]]
+;
+entry:
+ %0 = call <vscale x 2 x i32> @llvm.riscv.vle.nxv2i32.i64(<vscale x 2 x i32> poison, ptr %a, i64 8)
+ %1 = call <vscale x 2 x i32> @llvm.riscv.vle.nxv2i32.i64(<vscale x 2 x i32> poison, ptr %b, i64 8)
+ %2 = call <vscale x 2 x i32> @llvm.riscv.vadd.nxv2i32.nxv2i32.i64(<vscale x 2 x i32> poison, <vscale x 2 x i32> %0, <vscale x 2 x i32> %1, i64 8)
+ ret <vscale x 2 x i32> %2
+}
+
+; Function Attrs: nocallback nofree nosync nounwind willreturn memory(argmem: read)
+declare <vscale x 2 x i32> @llvm.riscv.vle.nxv2i32.i64(<vscale x 2 x i32>, ptr captures(none), i64) #1
+
+; Function Attrs: nocallback nofree nosync nounwind willreturn memory(none)
+declare <vscale x 2 x i32> @llvm.riscv.vadd.nxv2i32.nxv2i32.i64(<vscale x 2 x i32>, <vscale x 2 x i32>, <vscale x 2 x i32>, i64) #2
+
+
``````````
</details>
https://github.com/llvm/llvm-project/pull/138812
More information about the llvm-commits
mailing list