diff --git a/llvm/lib/Target/RISCV/RISCVTargetTransformInfo.h b/llvm/lib/Target/RISCV/RISCVTargetTransformInfo.h --- a/llvm/lib/Target/RISCV/RISCVTargetTransformInfo.h +++ b/llvm/lib/Target/RISCV/RISCVTargetTransformInfo.h @@ -83,6 +83,8 @@ unsigned getRegUsageForType(Type *Ty); + unsigned getMaximumVF(unsigned ElemWidth, unsigned Opcode) const; + InstructionCost getMaskedMemoryOpCost(unsigned Opcode, Type *Src, Align Alignment, unsigned AddressSpace, TTI::TargetCostKind CostKind); diff --git a/llvm/lib/Target/RISCV/RISCVTargetTransformInfo.cpp b/llvm/lib/Target/RISCV/RISCVTargetTransformInfo.cpp --- a/llvm/lib/Target/RISCV/RISCVTargetTransformInfo.cpp +++ b/llvm/lib/Target/RISCV/RISCVTargetTransformInfo.cpp @@ -24,6 +24,13 @@ "by autovectorized code. Fractional LMULs are not supported."), cl::init(1), cl::Hidden); +static cl::opt SLPMaxVF( + "riscv-v-slp-max-vf", + cl::desc( + "Result used for getMaximumVF query which is used exclusively by " + "SLP vectorizer. Defaults to 1 which disables SLP."), + cl::init(1), cl::Hidden); + InstructionCost RISCVTTIImpl::getIntImmCost(const APInt &Imm, Type *Ty, TTI::TargetCostKind CostKind) { assert(Ty->isIntegerTy() && @@ -999,3 +1006,12 @@ return BaseT::getRegUsageForType(Ty); } + +unsigned RISCVTTIImpl::getMaximumVF(unsigned ElemWidth, unsigned Opcode) const { + // This interface is currently only used by SLP. Returning 1 (which is the + // default value for SLPMaxVF) disables SLP. We currently have a cost modeling + // problem w/ constant materialization which causes SLP to perform majorly + // unprofitable transformations. + // TODO: Figure out constant materialization cost modeling and remove. + return SLPMaxVF; +} diff --git a/llvm/test/Transforms/SLPVectorizer/RISCV/load-store.ll b/llvm/test/Transforms/SLPVectorizer/RISCV/load-store.ll --- a/llvm/test/Transforms/SLPVectorizer/RISCV/load-store.ll +++ b/llvm/test/Transforms/SLPVectorizer/RISCV/load-store.ll @@ -1,6 +1,8 @@ ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py ; RUN: opt < %s -slp-vectorizer -mtriple=riscv64 -mattr=+v \ -; RUN: -riscv-v-vector-bits-min=-1 -S | FileCheck %s --check-prefixes=CHECK +; RUN: -riscv-v-vector-bits-min=-1 -riscv-v-slp-max-vf=0 -S | FileCheck %s --check-prefixes=CHECK +; RUN: opt < %s -slp-vectorizer -mtriple=riscv64 -mattr=+v -S | FileCheck %s --check-prefixes=DEFAULT + define void @simple_copy(ptr %dest, ptr %p) { ; CHECK-LABEL: @simple_copy( @@ -9,6 +11,16 @@ ; CHECK-NEXT: store <2 x i16> [[TMP0]], ptr [[DEST:%.*]], align 4 ; CHECK-NEXT: ret void ; +; DEFAULT-LABEL: @simple_copy( +; DEFAULT-NEXT: entry: +; DEFAULT-NEXT: [[E0:%.*]] = load i16, ptr [[P:%.*]], align 4 +; DEFAULT-NEXT: [[INC:%.*]] = getelementptr inbounds i16, ptr [[P]], i64 1 +; DEFAULT-NEXT: [[E1:%.*]] = load i16, ptr [[INC]], align 2 +; DEFAULT-NEXT: store i16 [[E0]], ptr [[DEST:%.*]], align 4 +; DEFAULT-NEXT: [[INC2:%.*]] = getelementptr inbounds i16, ptr [[DEST]], i64 1 +; DEFAULT-NEXT: store i16 [[E1]], ptr [[INC2]], align 2 +; DEFAULT-NEXT: ret void +; entry: %e0 = load i16, ptr %p, align 4 %inc = getelementptr inbounds i16, ptr %p, i64 1 @@ -28,6 +40,18 @@ ; CHECK-NEXT: store <2 x i16> [[TMP1]], ptr [[DEST:%.*]], align 4 ; CHECK-NEXT: ret void ; +; DEFAULT-LABEL: @vec_add( +; DEFAULT-NEXT: entry: +; DEFAULT-NEXT: [[E0:%.*]] = load i16, ptr [[P:%.*]], align 4 +; DEFAULT-NEXT: [[INC:%.*]] = getelementptr inbounds i16, ptr [[P]], i64 1 +; DEFAULT-NEXT: [[E1:%.*]] = load i16, ptr [[INC]], align 2 +; DEFAULT-NEXT: [[A0:%.*]] = add i16 [[E0]], 1 +; DEFAULT-NEXT: [[A1:%.*]] = add i16 [[E1]], 1 +; DEFAULT-NEXT: store i16 [[A0]], ptr [[DEST:%.*]], align 4 +; DEFAULT-NEXT: [[INC2:%.*]] = getelementptr inbounds i16, ptr [[DEST]], i64 1 +; DEFAULT-NEXT: store i16 [[A1]], ptr [[INC2]], align 2 +; DEFAULT-NEXT: ret void +; entry: %e0 = load i16, ptr %p, align 4 %inc = getelementptr inbounds i16, ptr %p, i64 1 @@ -52,6 +76,14 @@ ; CHECK-NEXT: store i16 [[E0]], ptr [[INC2]], align 2 ; CHECK-NEXT: ret void ; +; DEFAULT-LABEL: @splat_store( +; DEFAULT-NEXT: entry: +; DEFAULT-NEXT: [[E0:%.*]] = load i16, ptr [[P:%.*]], align 4 +; DEFAULT-NEXT: store i16 [[E0]], ptr [[DEST:%.*]], align 4 +; DEFAULT-NEXT: [[INC2:%.*]] = getelementptr inbounds i16, ptr [[DEST]], i64 1 +; DEFAULT-NEXT: store i16 [[E0]], ptr [[INC2]], align 2 +; DEFAULT-NEXT: ret void +; entry: %e0 = load i16, ptr %p, align 4 diff --git a/llvm/test/Transforms/SLPVectorizer/RISCV/rvv-min-vector-size.ll b/llvm/test/Transforms/SLPVectorizer/RISCV/rvv-min-vector-size.ll --- a/llvm/test/Transforms/SLPVectorizer/RISCV/rvv-min-vector-size.ll +++ b/llvm/test/Transforms/SLPVectorizer/RISCV/rvv-min-vector-size.ll @@ -1,10 +1,10 @@ ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py ; RUN: opt < %s -slp-vectorizer -mtriple=riscv64 -mattr=+v \ -; RUN: -riscv-v-vector-bits-min=128 -S | FileCheck %s --check-prefixes=CHECK,CHECK-128 +; RUN: -riscv-v-vector-bits-min=128 -riscv-v-slp-max-vf=0 -S | FileCheck %s --check-prefixes=CHECK,CHECK-128 ; RUN: opt < %s -slp-vectorizer -mtriple=riscv64 -mattr=+v \ -; RUN: -riscv-v-vector-bits-min=256 -S | FileCheck %s --check-prefixes=CHECK,CHECK-256 +; RUN: -riscv-v-vector-bits-min=256 -riscv-v-slp-max-vf=0 -S | FileCheck %s --check-prefixes=CHECK,CHECK-256 ; RUN: opt < %s -slp-vectorizer -mtriple=riscv64 -mattr=+v \ -; RUN: -riscv-v-vector-bits-min=512 -S | FileCheck %s --check-prefixes=CHECK,CHECK-512 +; RUN: -riscv-v-vector-bits-min=512 -riscv-v-slp-max-vf=0 -S | FileCheck %s --check-prefixes=CHECK,CHECK-512 target datalayout = "e-m:e-p:64:64-i64:64-i128:128-n64-S128" target triple = "riscv64"