[llvm] cc35161 - [RISCV] Add initial support for getRegUsageForType and getNumberOfRegisters

Kito Cheng via llvm-commits llvm-commits at lists.llvm.org
Sun Jan 16 23:27:59 PST 2022


Author: Kito Cheng
Date: 2022-01-17T15:27:54+08:00
New Revision: cc35161dc716ab5b0e66b15ac320ebd451a2bc44

URL: https://github.com/llvm/llvm-project/commit/cc35161dc716ab5b0e66b15ac320ebd451a2bc44
DIFF: https://github.com/llvm/llvm-project/commit/cc35161dc716ab5b0e66b15ac320ebd451a2bc44.diff

LOG: [RISCV] Add initial support for getRegUsageForType and getNumberOfRegisters

Those two TTI hooks are used during vectorization for calculating
register pressure, the default implementation isn't consider for LMUL,
and that's also definitly wrong value for register number (all register class
are 8 registers).

So in this patch we tried to:

1. Calculate right register usage for vector type and scalar type.
2. Return right number of register for general purpose register and
   vector register.

Reviewed By: craig.topper

Differential Revision: https://reviews.llvm.org/D116890

Added: 
    llvm/test/Transforms/LoopVectorize/RISCV/reg-usage.ll

Modified: 
    llvm/lib/Target/RISCV/RISCVSubtarget.h
    llvm/lib/Target/RISCV/RISCVTargetTransformInfo.cpp
    llvm/lib/Target/RISCV/RISCVTargetTransformInfo.h

Removed: 
    


################################################################################
diff  --git a/llvm/lib/Target/RISCV/RISCVSubtarget.h b/llvm/lib/Target/RISCV/RISCVSubtarget.h
index 36da6c0c97de6..0613166d1d0f1 100644
--- a/llvm/lib/Target/RISCV/RISCVSubtarget.h
+++ b/llvm/lib/Target/RISCV/RISCVSubtarget.h
@@ -161,6 +161,15 @@ class RISCVSubtarget : public RISCVGenSubtargetInfo {
   bool enableSaveRestore() const { return EnableSaveRestore; }
   MVT getXLenVT() const { return XLenVT; }
   unsigned getXLen() const { return XLen; }
+  unsigned getFLen() const {
+    if (HasStdExtD)
+      return 64;
+
+    if (HasStdExtF)
+      return 32;
+
+    return 0;
+  }
   RISCVABI::ABI getTargetABI() const { return TargetABI; }
   bool isRegisterReservedByUser(Register i) const {
     assert(i < RISCV::NUM_TARGET_REGS && "Register out of range");

diff  --git a/llvm/lib/Target/RISCV/RISCVTargetTransformInfo.cpp b/llvm/lib/Target/RISCV/RISCVTargetTransformInfo.cpp
index d20651615a15c..99e6774a02e4c 100644
--- a/llvm/lib/Target/RISCV/RISCVTargetTransformInfo.cpp
+++ b/llvm/lib/Target/RISCV/RISCVTargetTransformInfo.cpp
@@ -275,3 +275,16 @@ void RISCVTTIImpl::getPeelingPreferences(Loop *L, ScalarEvolution &SE,
                                          TTI::PeelingPreferences &PP) {
   BaseT::getPeelingPreferences(L, SE, PP);
 }
+
+InstructionCost RISCVTTIImpl::getRegUsageForType(Type *Ty) {
+  TypeSize Size = Ty->getPrimitiveSizeInBits();
+  if (Ty->isVectorTy()) {
+    if (Size.isScalable() && ST->hasVInstructions())
+      return divideCeil(Size.getKnownMinValue(), RISCV::RVVBitsPerBlock);
+
+    if (ST->useRVVForFixedLengthVectors())
+      return divideCeil(Size, ST->getMinRVVVectorSizeInBits());
+  }
+
+  return BaseT::getRegUsageForType(Ty);
+}

diff  --git a/llvm/lib/Target/RISCV/RISCVTargetTransformInfo.h b/llvm/lib/Target/RISCV/RISCVTargetTransformInfo.h
index a591be7718bbb..e79c4f75712b2 100644
--- a/llvm/lib/Target/RISCV/RISCVTargetTransformInfo.h
+++ b/llvm/lib/Target/RISCV/RISCVTargetTransformInfo.h
@@ -60,6 +60,8 @@ class RISCVTTIImpl : public BasicTTIImplBase<RISCVTTIImpl> {
 
   TypeSize getRegisterBitWidth(TargetTransformInfo::RegisterKind K) const;
 
+  InstructionCost getRegUsageForType(Type *Ty);
+
   void getUnrollingPreferences(Loop *L, ScalarEvolution &SE,
                                TTI::UnrollingPreferences &UP,
                                OptimizationRemarkEmitter *ORE);
@@ -176,6 +178,20 @@ class RISCVTTIImpl : public BasicTTIImplBase<RISCVTTIImpl> {
     // Let regular unroll to unroll the loop.
     return VF == 1 ? 1 : ST->getMaxInterleaveFactor();
   }
+
+  // TODO: We should define RISC-V's own register classes.
+  //       e.g. register class for FPR.
+  unsigned getNumberOfRegisters(unsigned ClassID) const {
+    bool Vector = (ClassID == 1);
+    if (Vector) {
+      if (ST->hasVInstructions())
+        return 32;
+      return 0;
+    }
+    // 31 = 32 GPR - x0 (zero register)
+    // FIXME: Should we exclude fixed registers like SP, TP or GP?
+    return 31;
+  }
 };
 
 } // end namespace llvm

diff  --git a/llvm/test/Transforms/LoopVectorize/RISCV/reg-usage.ll b/llvm/test/Transforms/LoopVectorize/RISCV/reg-usage.ll
new file mode 100644
index 0000000000000..4d6508b683770
--- /dev/null
+++ b/llvm/test/Transforms/LoopVectorize/RISCV/reg-usage.ll
@@ -0,0 +1,62 @@
+; REQUIRES: asserts
+; RUN: opt -loop-vectorize -mtriple riscv64-linux-gnu \
+; RUN:   -mattr=+experimental-v,+d -debug-only=loop-vectorize \
+; RUN:   -riscv-v-vector-bits-min=128 -riscv-v-register-bit-width-lmul=1 \
+; RUN:   -S < %s 2>&1 | FileCheck %s --check-prefix=CHECK-LMUL1
+; RUN: opt -loop-vectorize -mtriple riscv64-linux-gnu \
+; RUN:   -mattr=+experimental-v,+d -debug-only=loop-vectorize \
+; RUN:   -riscv-v-vector-bits-min=128 -riscv-v-register-bit-width-lmul=2 \
+; RUN:   -S < %s 2>&1 | FileCheck %s --check-prefix=CHECK-LMUL2
+; RUN: opt -loop-vectorize -mtriple riscv64-linux-gnu \
+; RUN:   -mattr=+experimental-v,+d -debug-only=loop-vectorize \
+; RUN:   -riscv-v-vector-bits-min=128 -riscv-v-register-bit-width-lmul=4 \
+; RUN:   -S < %s 2>&1 | FileCheck %s --check-prefix=CHECK-LMUL4
+; RUN: opt -loop-vectorize -mtriple riscv64-linux-gnu \
+; RUN:   -mattr=+experimental-v,+d -debug-only=loop-vectorize \
+; RUN:   -riscv-v-vector-bits-min=128 -riscv-v-register-bit-width-lmul=8 \
+; RUN:   -S < %s 2>&1 | FileCheck %s --check-prefix=CHECK-LMUL8
+
+define void @add(float* noalias nocapture readonly %src1, float* noalias nocapture readonly %src2, i32 signext %size, float* noalias nocapture writeonly %result) {
+; CHECK-LABEL: add
+; CHECK-LMUL1:      LV(REG): Found max usage: 2 item
+; CHECK-LMUL1-NEXT: LV(REG): RegisterClass: Generic::ScalarRC, 2 registers
+; CHECK-LMUL1-NEXT: LV(REG): RegisterClass: Generic::VectorRC, 2 registers
+; CHECK-LMUL1-NEXT: LV(REG): Found invariant usage: 1 item
+; CHECK-LMUL1-NEXT: LV(REG): RegisterClass: Generic::VectorRC, 2 registers
+; CHECK-LMUL2:      LV(REG): Found max usage: 2 item
+; CHECK-LMUL2-NEXT: LV(REG): RegisterClass: Generic::ScalarRC, 2 registers
+; CHECK-LMUL2-NEXT: LV(REG): RegisterClass: Generic::VectorRC, 4 registers
+; CHECK-LMUL2-NEXT: LV(REG): Found invariant usage: 1 item
+; CHECK-LMUL2-NEXT: LV(REG): RegisterClass: Generic::VectorRC, 4 registers
+; CHECK-LMUL4:      LV(REG): Found max usage: 2 item
+; CHECK-LMUL4-NEXT: LV(REG): RegisterClass: Generic::ScalarRC, 2 registers
+; CHECK-LMUL4-NEXT: LV(REG): RegisterClass: Generic::VectorRC, 8 registers
+; CHECK-LMUL4-NEXT: LV(REG): Found invariant usage: 1 item
+; CHECK-LMUL4-NEXT: LV(REG): RegisterClass: Generic::VectorRC, 8 registers
+; CHECK-LMUL8:      LV(REG): Found max usage: 2 item
+; CHECK-LMUL8-NEXT: LV(REG): RegisterClass: Generic::ScalarRC, 2 registers
+; CHECK-LMUL8-NEXT: LV(REG): RegisterClass: Generic::VectorRC, 16 registers
+; CHECK-LMUL8-NEXT: LV(REG): Found invariant usage: 1 item
+; CHECK-LMUL8-NEXT: LV(REG): RegisterClass: Generic::VectorRC, 16 registers
+
+entry:
+  %conv = zext i32 %size to i64
+  %cmp10.not = icmp eq i32 %size, 0
+  br i1 %cmp10.not, label %for.cond.cleanup, label %for.body
+
+for.cond.cleanup:
+  ret void
+
+for.body:
+  %i.011 = phi i64 [ %add4, %for.body ], [ 0, %entry ]
+  %arrayidx = getelementptr inbounds float, float* %src1, i64 %i.011
+  %0 = load float, float* %arrayidx, align 4
+  %arrayidx2 = getelementptr inbounds float, float* %src2, i64 %i.011
+  %1 = load float, float* %arrayidx2, align 4
+  %add = fadd float %0, %1
+  %arrayidx3 = getelementptr inbounds float, float* %result, i64 %i.011
+  store float %add, float* %arrayidx3, align 4
+  %add4 = add nuw nsw i64 %i.011, 1
+  %exitcond.not = icmp eq i64 %add4, %conv
+  br i1 %exitcond.not, label %for.cond.cleanup, label %for.body
+}


        


More information about the llvm-commits mailing list