mirror of
https://github.com/intel/llvm.git
synced 2026-02-08 17:28:30 +08:00
[RISCV] Enable LoopDataPrefetch pass (#66201)
So that we can benefit from data prefetch when `Zicbop` extension is supported. Tune information for data prefetching are added in `RISCVTuneInfo`.
This commit is contained in:
@@ -13,12 +13,20 @@
|
||||
class RISCVTuneInfo {
|
||||
bits<8> PrefFunctionAlignment = 1;
|
||||
bits<8> PrefLoopAlignment = 1;
|
||||
|
||||
// Information needed by LoopDataPrefetch.
|
||||
bits<16> CacheLineSize = 0;
|
||||
bits<16> PrefetchDistance = 0;
|
||||
bits<16> MinPrefetchStride = 1;
|
||||
bits<32> MaxPrefetchIterationsAhead = -1;
|
||||
}
|
||||
|
||||
def RISCVTuneInfoTable : GenericTable {
|
||||
let FilterClass = "RISCVTuneInfo";
|
||||
let CppTypeName = "RISCVTuneInfo";
|
||||
let Fields = ["Name", "PrefFunctionAlignment", "PrefLoopAlignment"];
|
||||
let Fields = ["Name", "PrefFunctionAlignment", "PrefLoopAlignment",
|
||||
"CacheLineSize", "PrefetchDistance",
|
||||
"MinPrefetchStride", "MaxPrefetchIterationsAhead"];
|
||||
}
|
||||
|
||||
def getRISCVTuneInfo : SearchIndex {
|
||||
|
||||
@@ -38,6 +38,12 @@ struct RISCVTuneInfo {
|
||||
const char *Name;
|
||||
uint8_t PrefFunctionAlignment;
|
||||
uint8_t PrefLoopAlignment;
|
||||
|
||||
// Information needed by LoopDataPrefetch.
|
||||
uint16_t CacheLineSize;
|
||||
uint16_t PrefetchDistance;
|
||||
uint16_t MinPrefetchStride;
|
||||
unsigned MaxPrefetchIterationsAhead;
|
||||
};
|
||||
|
||||
#define GET_RISCVTuneInfoTable_DECL
|
||||
@@ -248,6 +254,22 @@ public:
|
||||
&Mutations) const override;
|
||||
|
||||
bool useAA() const override;
|
||||
|
||||
unsigned getCacheLineSize() const override {
|
||||
return TuneInfo->CacheLineSize;
|
||||
};
|
||||
unsigned getPrefetchDistance() const override {
|
||||
return TuneInfo->PrefetchDistance;
|
||||
};
|
||||
unsigned getMinPrefetchStride(unsigned NumMemAccesses,
|
||||
unsigned NumStridedMemAccesses,
|
||||
unsigned NumPrefetches,
|
||||
bool HasCall) const override {
|
||||
return TuneInfo->MinPrefetchStride;
|
||||
};
|
||||
unsigned getMaxPrefetchIterationsAhead() const override {
|
||||
return TuneInfo->MaxPrefetchIterationsAhead;
|
||||
};
|
||||
};
|
||||
} // End llvm namespace
|
||||
|
||||
|
||||
@@ -34,6 +34,7 @@
|
||||
#include "llvm/Support/FormattedStream.h"
|
||||
#include "llvm/Target/TargetOptions.h"
|
||||
#include "llvm/Transforms/IPO.h"
|
||||
#include "llvm/Transforms/Scalar.h"
|
||||
#include <optional>
|
||||
using namespace llvm;
|
||||
|
||||
@@ -83,6 +84,11 @@ static cl::opt<bool>
|
||||
cl::desc("Enable sinking and folding of instruction copies"),
|
||||
cl::init(false), cl::Hidden);
|
||||
|
||||
static cl::opt<bool>
|
||||
EnableLoopDataPrefetch("riscv-enable-loop-data-prefetch", cl::Hidden,
|
||||
cl::desc("Enable the loop data prefetch pass"),
|
||||
cl::init(true));
|
||||
|
||||
extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeRISCVTarget() {
|
||||
RegisterTargetMachine<RISCVTargetMachine> X(getTheRISCV32Target());
|
||||
RegisterTargetMachine<RISCVTargetMachine> Y(getTheRISCV64Target());
|
||||
@@ -310,6 +316,9 @@ void RISCVPassConfig::addIRPasses() {
|
||||
addPass(createAtomicExpandPass());
|
||||
|
||||
if (getOptLevel() != CodeGenOptLevel::None) {
|
||||
if (EnableLoopDataPrefetch)
|
||||
addPass(createLoopDataPrefetchPass());
|
||||
|
||||
addPass(createRISCVGatherScatterLoweringPass());
|
||||
addPass(createInterleavedAccessPass());
|
||||
addPass(createRISCVCodeGenPreparePass());
|
||||
|
||||
@@ -12,10 +12,10 @@
|
||||
; CHECK-NEXT: Target Pass Configuration
|
||||
; CHECK-NEXT: Machine Module Information
|
||||
; CHECK-NEXT: Target Transform Information
|
||||
; CHECK-NEXT: Type-Based Alias Analysis
|
||||
; CHECK-NEXT: Scoped NoAlias Alias Analysis
|
||||
; CHECK-NEXT: Assumption Cache Tracker
|
||||
; CHECK-NEXT: Profile summary info
|
||||
; CHECK-NEXT: Type-Based Alias Analysis
|
||||
; CHECK-NEXT: Scoped NoAlias Alias Analysis
|
||||
; CHECK-NEXT: Create Garbage Collector Module Metadata
|
||||
; CHECK-NEXT: Machine Branch Probability Analysis
|
||||
; CHECK-NEXT: Default Regalloc Eviction Advisor
|
||||
@@ -28,6 +28,12 @@
|
||||
; CHECK-NEXT: Expand Atomic instructions
|
||||
; CHECK-NEXT: Dominator Tree Construction
|
||||
; CHECK-NEXT: Natural Loop Information
|
||||
; CHECK-NEXT: Canonicalize natural loops
|
||||
; CHECK-NEXT: Lazy Branch Probability Analysis
|
||||
; CHECK-NEXT: Lazy Block Frequency Analysis
|
||||
; CHECK-NEXT: Optimization Remark Emitter
|
||||
; CHECK-NEXT: Scalar Evolution Analysis
|
||||
; CHECK-NEXT: Loop Data Prefetch
|
||||
; CHECK-NEXT: RISC-V gather/scatter lowering
|
||||
; CHECK-NEXT: Interleaved Access Pass
|
||||
; CHECK-NEXT: RISC-V CodeGenPrepare
|
||||
|
||||
43
llvm/test/Transforms/LoopDataPrefetch/RISCV/basic.ll
Normal file
43
llvm/test/Transforms/LoopDataPrefetch/RISCV/basic.ll
Normal file
@@ -0,0 +1,43 @@
|
||||
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 3
|
||||
; RUN: opt -mtriple=riscv64 -cache-line-size=64 -prefetch-distance=64 \
|
||||
; RUN: -passes=loop-data-prefetch -S < %s | FileCheck %s
|
||||
|
||||
define void @foo(ptr nocapture %a, ptr nocapture readonly %b) {
|
||||
; CHECK-LABEL: define void @foo(
|
||||
; CHECK-SAME: ptr nocapture [[A:%.*]], ptr nocapture readonly [[B:%.*]]) {
|
||||
; CHECK-NEXT: entry:
|
||||
; CHECK-NEXT: br label [[FOR_BODY:%.*]]
|
||||
; CHECK: for.body:
|
||||
; CHECK-NEXT: [[INDVARS_IV:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[INDVARS_IV_NEXT:%.*]], [[FOR_BODY]] ]
|
||||
; CHECK-NEXT: [[TMP0:%.*]] = shl nuw nsw i64 [[INDVARS_IV]], 3
|
||||
; CHECK-NEXT: [[TMP1:%.*]] = add i64 [[TMP0]], 64
|
||||
; CHECK-NEXT: [[SCEVGEP:%.*]] = getelementptr i8, ptr [[B]], i64 [[TMP1]]
|
||||
; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds double, ptr [[B]], i64 [[INDVARS_IV]]
|
||||
; CHECK-NEXT: call void @llvm.prefetch.p0(ptr [[SCEVGEP]], i32 0, i32 3, i32 1)
|
||||
; CHECK-NEXT: [[TMP2:%.*]] = load double, ptr [[ARRAYIDX]], align 8
|
||||
; CHECK-NEXT: [[ADD:%.*]] = fadd double [[TMP2]], 1.000000e+00
|
||||
; CHECK-NEXT: [[ARRAYIDX2:%.*]] = getelementptr inbounds double, ptr [[A]], i64 [[INDVARS_IV]]
|
||||
; CHECK-NEXT: store double [[ADD]], ptr [[ARRAYIDX2]], align 8
|
||||
; CHECK-NEXT: [[INDVARS_IV_NEXT]] = add nuw nsw i64 [[INDVARS_IV]], 1
|
||||
; CHECK-NEXT: [[EXITCOND:%.*]] = icmp eq i64 [[INDVARS_IV_NEXT]], 1600
|
||||
; CHECK-NEXT: br i1 [[EXITCOND]], label [[FOR_END:%.*]], label [[FOR_BODY]]
|
||||
; CHECK: for.end:
|
||||
; CHECK-NEXT: ret void
|
||||
;
|
||||
entry:
|
||||
br label %for.body
|
||||
|
||||
for.body: ; preds = %for.body, %entry
|
||||
%indvars.iv = phi i64 [ 0, %entry ], [ %indvars.iv.next, %for.body ]
|
||||
%arrayidx = getelementptr inbounds double, ptr %b, i64 %indvars.iv
|
||||
%0 = load double, ptr %arrayidx, align 8
|
||||
%add = fadd double %0, 1.000000e+00
|
||||
%arrayidx2 = getelementptr inbounds double, ptr %a, i64 %indvars.iv
|
||||
store double %add, ptr %arrayidx2, align 8
|
||||
%indvars.iv.next = add nuw nsw i64 %indvars.iv, 1
|
||||
%exitcond = icmp eq i64 %indvars.iv.next, 1600
|
||||
br i1 %exitcond, label %for.end, label %for.body
|
||||
|
||||
for.end: ; preds = %for.body
|
||||
ret void
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
if not "RISCV" in config.root.targets:
|
||||
config.unsupported = True
|
||||
Reference in New Issue
Block a user