[flang-commits] [flang] [Flang][RISCV] Set vscale_range based off zvl*b (PR #77277)

Luke Lau via flang-commits flang-commits at lists.llvm.org
Thu Jan 11 01:30:01 PST 2024


https://github.com/lukel97 updated https://github.com/llvm/llvm-project/pull/77277

>From bfa95458f113817c72d06c29ed373551cd394d62 Mon Sep 17 00:00:00 2001
From: Luke Lau <luke at igalia.com>
Date: Mon, 8 Jan 2024 13:55:46 +0700
Subject: [PATCH 1/3] [Flang][RISCV] Set vscale_range based off zvl*b

This patch copies the logic from RISCVTargetInfo::getVScaleRange so that we can
compute the vscale_range based off of the zvl*b extension, e.g. zvl256b now
implies vscale_range(2,1024).

It's not ideal having to duplicate this code, but using TargetInfo is another
task altogether.

This also adds a guard for +sve so that we only check for it on aarch64, which was the behaviour prior to 898db1136e679
---
 flang/lib/Frontend/FrontendActions.cpp        | 56 +++++++++++++++++--
 .../RISCV/riscv-vector-bits-vscale-range.f90  | 21 +++++--
 2 files changed, 65 insertions(+), 12 deletions(-)

diff --git a/flang/lib/Frontend/FrontendActions.cpp b/flang/lib/Frontend/FrontendActions.cpp
index d4a3e164d20739..a8a3ed6ee6934a 100644
--- a/flang/lib/Frontend/FrontendActions.cpp
+++ b/flang/lib/Frontend/FrontendActions.cpp
@@ -63,9 +63,11 @@
 #include "llvm/Support/ErrorHandling.h"
 #include "llvm/Support/FileSystem.h"
 #include "llvm/Support/Path.h"
+#include "llvm/Support/RISCVISAInfo.h"
 #include "llvm/Support/SourceMgr.h"
 #include "llvm/Support/ToolOutputFile.h"
 #include "llvm/Target/TargetMachine.h"
+#include "llvm/TargetParser/RISCVTargetParser.h"
 #include "llvm/Transforms/Utils/ModuleUtils.h"
 #include <memory>
 #include <system_error>
@@ -712,13 +714,55 @@ void CodeGenAction::lowerHLFIRToFIR() {
 static std::optional<std::pair<unsigned, unsigned>>
 getVScaleRange(CompilerInstance &ci) {
   const auto &langOpts = ci.getInvocation().getLangOpts();
-  if (langOpts.VScaleMin || langOpts.VScaleMax)
-    return std::pair<unsigned, unsigned>(
-        langOpts.VScaleMin ? langOpts.VScaleMin : 1, langOpts.VScaleMax);
+  const auto targetOpts = ci.getInvocation().getTargetOpts();
+  const llvm::Triple triple(targetOpts.triple);
+
+  if (triple.isAArch64()) {
+    if (langOpts.VScaleMin || langOpts.VScaleMax)
+      return std::pair<unsigned, unsigned>(
+          langOpts.VScaleMin ? langOpts.VScaleMin : 1, langOpts.VScaleMax);
+
+    std::string featuresStr = ci.getTargetFeatures();
+    if (featuresStr.find("+sve") != std::string::npos)
+      return std::pair<unsigned, unsigned>(1, 16);
+  } else if (triple.isRISCV()) {
+    auto parseResult = llvm::RISCVISAInfo::parseFeatures(
+        triple.isRISCV64() ? 64 : 32, targetOpts.featuresAsWritten);
+    if (!parseResult) {
+      std::string buffer;
+      llvm::raw_string_ostream outputErrMsg(buffer);
+      handleAllErrors(parseResult.takeError(), [&](llvm::StringError &errMsg) {
+        outputErrMsg << errMsg.getMessage();
+      });
+      ci.getDiagnostics().Report(clang::diag::err_invalid_feature_combination)
+          << outputErrMsg.str();
+      return std::nullopt;
+    }
+
+    llvm::RISCVISAInfo *const isaInfo = parseResult->get();
 
-  std::string featuresStr = ci.getTargetFeatures();
-  if (featuresStr.find("+sve") != std::string::npos)
-    return std::pair<unsigned, unsigned>(1, 16);
+    // RISCV::RVVBitsPerBlock is 64.
+    unsigned vscaleMin = isaInfo->getMinVLen() / llvm::RISCV::RVVBitsPerBlock;
+
+    if (langOpts.VScaleMin || langOpts.VScaleMax) {
+      // Treat Zvl*b as a lower bound on vscale.
+      vscaleMin = std::max(vscaleMin, langOpts.VScaleMin);
+      unsigned vscaleMax = langOpts.VScaleMax;
+      if (vscaleMax != 0 && vscaleMax < vscaleMin)
+        vscaleMax = vscaleMin;
+      return std::pair<unsigned, unsigned>(vscaleMin ? vscaleMin : 1,
+                                           vscaleMax);
+    }
+
+    if (vscaleMin > 0) {
+      unsigned vscaleMax = isaInfo->getMaxVLen() / llvm::RISCV::RVVBitsPerBlock;
+      return std::make_pair(vscaleMin, vscaleMax);
+    }
+  } else {
+    if (langOpts.VScaleMin || langOpts.VScaleMax)
+      return std::pair<unsigned, unsigned>(
+          langOpts.VScaleMin ? langOpts.VScaleMin : 1, langOpts.VScaleMax);
+  }
 
   return std::nullopt;
 }
diff --git a/flang/test/Lower/RISCV/riscv-vector-bits-vscale-range.f90 b/flang/test/Lower/RISCV/riscv-vector-bits-vscale-range.f90
index b08ad91feb3884..f1f06707cd6827 100644
--- a/flang/test/Lower/RISCV/riscv-vector-bits-vscale-range.f90
+++ b/flang/test/Lower/RISCV/riscv-vector-bits-vscale-range.f90
@@ -1,21 +1,30 @@
 ! REQUIRES: riscv-registered-target
-! RUN: %flang_fc1 -triple riscv64-none-linux-gnu -target-feature +v -mvscale-min=1 -mvscale-max=1  -emit-llvm -o - %s | FileCheck %s -D#VBITS=1
+! RUN: %flang_fc1 -triple riscv64-none-linux-gnu -target-feature +v -mvscale-min=1 -mvscale-max=1  -emit-llvm -o - %s | FileCheck %s -D#VBITS=2
 ! RUN: %flang_fc1 -triple riscv64-none-linux-gnu -target-feature +v -mvscale-min=2 -mvscale-max=2  -emit-llvm -o - %s | FileCheck %s -D#VBITS=2
 ! RUN: %flang_fc1 -triple riscv64-none-linux-gnu -target-feature +v -mvscale-min=4 -mvscale-max=4  -emit-llvm -o - %s | FileCheck %s -D#VBITS=4
 ! RUN: %flang_fc1 -triple riscv64-none-linux-gnu -target-feature +v -mvscale-min=8 -mvscale-max=8  -emit-llvm -o - %s | FileCheck %s -D#VBITS=8
 ! RUN: %flang_fc1 -triple riscv64-none-linux-gnu -target-feature +v -mvscale-min=16 -mvscale-max=16  -emit-llvm -o - %s | FileCheck %s -D#VBITS=16
-! RUN: %flang_fc1 -triple riscv64-none-linux-gnu -target-feature +v -mvscale-min=1  -emit-llvm -o - %s | FileCheck %s -D#VBITS=1 --check-prefix=CHECK-NOMAX
+! RUN: %flang_fc1 -triple riscv64-none-linux-gnu -target-feature +v -mvscale-min=2 -mvscale-max=2  -emit-llvm -o - %s | FileCheck %s -D#VBITS=2
+! RUN: %flang_fc1 -triple riscv64-none-linux-gnu -target-feature +v -mvscale-min=4 -mvscale-max=4  -emit-llvm -o - %s | FileCheck %s -D#VBITS=4
+! RUN: %flang_fc1 -triple riscv64-none-linux-gnu -target-feature +v -mvscale-min=8 -mvscale-max=8  -emit-llvm -o - %s | FileCheck %s -D#VBITS=8
+! RUN: %flang_fc1 -triple riscv64-none-linux-gnu -target-feature +v -mvscale-min=16 -mvscale-max=16  -emit-llvm -o - %s | FileCheck %s -D#VBITS=16
+! RUN: %flang_fc1 -triple riscv64-none-linux-gnu -target-feature +v -mvscale-min=1  -emit-llvm -o - %s | FileCheck %s -D#VBITS=2 --check-prefix=CHECK-NOMAX
 ! RUN: %flang_fc1 -triple riscv64-none-linux-gnu -target-feature +v -mvscale-min=2  -emit-llvm -o - %s | FileCheck %s -D#VBITS=2 --check-prefix=CHECK-NOMAX
 ! RUN: %flang_fc1 -triple riscv64-none-linux-gnu -target-feature +v -mvscale-min=4  -emit-llvm -o - %s | FileCheck %s -D#VBITS=4 --check-prefix=CHECK-NOMAX
 ! RUN: %flang_fc1 -triple riscv64-none-linux-gnu -target-feature +v -mvscale-min=8  -emit-llvm -o - %s | FileCheck %s -D#VBITS=8 --check-prefix=CHECK-NOMAX
 ! RUN: %flang_fc1 -triple riscv64-none-linux-gnu -target-feature +v -mvscale-min=16  -emit-llvm -o - %s | FileCheck %s -D#VBITS=16 --check-prefix=CHECK-NOMAX
-! RUN: %flang_fc1 -triple riscv64-none-linux-gnu -target-feature +v -mvscale-min=1 -mvscale-max=0  -emit-llvm -o - %s | FileCheck %s --check-prefix=CHECK-UNBOUNDED
-! RUN: %flang_fc1 -triple riscv64-none-linux-gnu -target-feature +v -emit-llvm -o - %s | FileCheck %s --check-prefix=CHECK-NONE
+! RUN: %flang_fc1 -triple riscv64-none-linux-gnu -target-feature +v -mvscale-min=1 -mvscale-max=0 -emit-llvm -o - %s | FileCheck %s -D#VBITS=2 --check-prefix=CHECK-UNBOUNDED
+! RUN: %flang_fc1 -triple riscv64-none-linux-gnu -target-feature +zve64x -target-feature +zvl64b -emit-llvm -o - %s | FileCheck %s -D#VBITS=1 -check-prefix=CHECK-ZVL
+! RUN: %flang_fc1 -triple riscv64-none-linux-gnu -target-feature +v -emit-llvm -o - %s | FileCheck %s -D#VBITS=2 -check-prefix=CHECK-ZVL
+! RUN: %flang_fc1 -triple riscv64-none-linux-gnu -target-feature +zve64x -target-feature +zvl128b -emit-llvm -o - %s | FileCheck %s -D#VBITS=2 -check-prefix=CHECK-ZVL
+! RUN: %flang_fc1 -triple riscv64-none-linux-gnu -target-feature +zve64x -target-feature +zvl256b -emit-llvm -o - %s | FileCheck %s -D#VBITS=4 -check-prefix=CHECK-ZVL
+! RUN: %flang_fc1 -triple riscv64-none-linux-gnu -target-feature +zve64x -target-feature +zvl512b -emit-llvm -o - %s | FileCheck %s -D#VBITS=8 -check-prefix=CHECK-ZVL
+! RUN: %flang_fc1 -triple riscv64-none-linux-gnu -target-feature +zve64x -target-feature +zvl1024b -emit-llvm -o - %s | FileCheck %s -D#VBITS=16 -check-prefix=CHECK-ZVL
 
 ! CHECK-LABEL: @func_() #0
 ! CHECK: attributes #0 = {{{.*}} vscale_range([[#VBITS]],[[#VBITS]]) {{.*}}}
 ! CHECK-NOMAX: attributes #0 = {{{.*}} vscale_range([[#VBITS]],0) {{.*}}}
-! CHECK-UNBOUNDED: attributes #0 = {{{.*}} vscale_range(1,0) {{.*}}}
-! CHECK-NONE-NOT: vscale_range
+! CHECK-UNBOUNDED: attributes #0 = {{{.*}} vscale_range(2,0) {{.*}}}
+! CHECK-ZVL: attributes #0 = {{{.*}} vscale_range([[#VBITS]],1024) {{.*}}}
 subroutine func
 end subroutine func

>From f36224bc7e54998651862ded9da1a0ae09a8a51d Mon Sep 17 00:00:00 2001
From: Luke Lau <luke at igalia.com>
Date: Mon, 8 Jan 2024 14:07:42 +0700
Subject: [PATCH 2/3] Remove accidental duplicate RUN lines

---
 flang/test/Lower/RISCV/riscv-vector-bits-vscale-range.f90 | 4 ----
 1 file changed, 4 deletions(-)

diff --git a/flang/test/Lower/RISCV/riscv-vector-bits-vscale-range.f90 b/flang/test/Lower/RISCV/riscv-vector-bits-vscale-range.f90
index f1f06707cd6827..d7fc6ad0a62c36 100644
--- a/flang/test/Lower/RISCV/riscv-vector-bits-vscale-range.f90
+++ b/flang/test/Lower/RISCV/riscv-vector-bits-vscale-range.f90
@@ -4,10 +4,6 @@
 ! RUN: %flang_fc1 -triple riscv64-none-linux-gnu -target-feature +v -mvscale-min=4 -mvscale-max=4  -emit-llvm -o - %s | FileCheck %s -D#VBITS=4
 ! RUN: %flang_fc1 -triple riscv64-none-linux-gnu -target-feature +v -mvscale-min=8 -mvscale-max=8  -emit-llvm -o - %s | FileCheck %s -D#VBITS=8
 ! RUN: %flang_fc1 -triple riscv64-none-linux-gnu -target-feature +v -mvscale-min=16 -mvscale-max=16  -emit-llvm -o - %s | FileCheck %s -D#VBITS=16
-! RUN: %flang_fc1 -triple riscv64-none-linux-gnu -target-feature +v -mvscale-min=2 -mvscale-max=2  -emit-llvm -o - %s | FileCheck %s -D#VBITS=2
-! RUN: %flang_fc1 -triple riscv64-none-linux-gnu -target-feature +v -mvscale-min=4 -mvscale-max=4  -emit-llvm -o - %s | FileCheck %s -D#VBITS=4
-! RUN: %flang_fc1 -triple riscv64-none-linux-gnu -target-feature +v -mvscale-min=8 -mvscale-max=8  -emit-llvm -o - %s | FileCheck %s -D#VBITS=8
-! RUN: %flang_fc1 -triple riscv64-none-linux-gnu -target-feature +v -mvscale-min=16 -mvscale-max=16  -emit-llvm -o - %s | FileCheck %s -D#VBITS=16
 ! RUN: %flang_fc1 -triple riscv64-none-linux-gnu -target-feature +v -mvscale-min=1  -emit-llvm -o - %s | FileCheck %s -D#VBITS=2 --check-prefix=CHECK-NOMAX
 ! RUN: %flang_fc1 -triple riscv64-none-linux-gnu -target-feature +v -mvscale-min=2  -emit-llvm -o - %s | FileCheck %s -D#VBITS=2 --check-prefix=CHECK-NOMAX
 ! RUN: %flang_fc1 -triple riscv64-none-linux-gnu -target-feature +v -mvscale-min=4  -emit-llvm -o - %s | FileCheck %s -D#VBITS=4 --check-prefix=CHECK-NOMAX

>From f2269046ad2d7cc9abff41498bf29df5a9968d4f Mon Sep 17 00:00:00 2001
From: Luke Lau <luke at igalia.com>
Date: Thu, 11 Jan 2024 16:29:13 +0700
Subject: [PATCH 3/3] Early return with std::nullopt, split up into separate
 functions per target

---
 flang/lib/Frontend/FrontendActions.cpp | 105 ++++++++++++++-----------
 1 file changed, 61 insertions(+), 44 deletions(-)

diff --git a/flang/lib/Frontend/FrontendActions.cpp b/flang/lib/Frontend/FrontendActions.cpp
index a8a3ed6ee6934a..23bcab0676a8bc 100644
--- a/flang/lib/Frontend/FrontendActions.cpp
+++ b/flang/lib/Frontend/FrontendActions.cpp
@@ -709,64 +709,81 @@ void CodeGenAction::lowerHLFIRToFIR() {
   }
 }
 
-// TODO: We should get this from TargetInfo. However, that depends on
-// too much of clang, so for now, replicate the functionality.
 static std::optional<std::pair<unsigned, unsigned>>
-getVScaleRange(CompilerInstance &ci) {
+getAArch64VScaleRange(CompilerInstance &ci) {
+  const auto &langOpts = ci.getInvocation().getLangOpts();
+
+  if (langOpts.VScaleMin || langOpts.VScaleMax)
+    return std::pair<unsigned, unsigned>(
+        langOpts.VScaleMin ? langOpts.VScaleMin : 1, langOpts.VScaleMax);
+
+  std::string featuresStr = ci.getTargetFeatures();
+  if (featuresStr.find("+sve") != std::string::npos)
+    return std::pair<unsigned, unsigned>(1, 16);
+
+  return std::nullopt;
+}
+
+static std::optional<std::pair<unsigned, unsigned>>
+getRISCVVScaleRange(CompilerInstance &ci) {
   const auto &langOpts = ci.getInvocation().getLangOpts();
   const auto targetOpts = ci.getInvocation().getTargetOpts();
   const llvm::Triple triple(targetOpts.triple);
 
-  if (triple.isAArch64()) {
-    if (langOpts.VScaleMin || langOpts.VScaleMax)
-      return std::pair<unsigned, unsigned>(
-          langOpts.VScaleMin ? langOpts.VScaleMin : 1, langOpts.VScaleMax);
-
-    std::string featuresStr = ci.getTargetFeatures();
-    if (featuresStr.find("+sve") != std::string::npos)
-      return std::pair<unsigned, unsigned>(1, 16);
-  } else if (triple.isRISCV()) {
-    auto parseResult = llvm::RISCVISAInfo::parseFeatures(
-        triple.isRISCV64() ? 64 : 32, targetOpts.featuresAsWritten);
-    if (!parseResult) {
-      std::string buffer;
-      llvm::raw_string_ostream outputErrMsg(buffer);
-      handleAllErrors(parseResult.takeError(), [&](llvm::StringError &errMsg) {
-        outputErrMsg << errMsg.getMessage();
-      });
-      ci.getDiagnostics().Report(clang::diag::err_invalid_feature_combination)
-          << outputErrMsg.str();
-      return std::nullopt;
-    }
+  auto parseResult = llvm::RISCVISAInfo::parseFeatures(
+      triple.isRISCV64() ? 64 : 32, targetOpts.featuresAsWritten);
+  if (!parseResult) {
+    std::string buffer;
+    llvm::raw_string_ostream outputErrMsg(buffer);
+    handleAllErrors(parseResult.takeError(), [&](llvm::StringError &errMsg) {
+      outputErrMsg << errMsg.getMessage();
+    });
+    ci.getDiagnostics().Report(clang::diag::err_invalid_feature_combination)
+        << outputErrMsg.str();
+    return std::nullopt;
+  }
 
-    llvm::RISCVISAInfo *const isaInfo = parseResult->get();
+  llvm::RISCVISAInfo *const isaInfo = parseResult->get();
 
-    // RISCV::RVVBitsPerBlock is 64.
-    unsigned vscaleMin = isaInfo->getMinVLen() / llvm::RISCV::RVVBitsPerBlock;
+  // RISCV::RVVBitsPerBlock is 64.
+  unsigned vscaleMin = isaInfo->getMinVLen() / llvm::RISCV::RVVBitsPerBlock;
 
-    if (langOpts.VScaleMin || langOpts.VScaleMax) {
-      // Treat Zvl*b as a lower bound on vscale.
-      vscaleMin = std::max(vscaleMin, langOpts.VScaleMin);
-      unsigned vscaleMax = langOpts.VScaleMax;
-      if (vscaleMax != 0 && vscaleMax < vscaleMin)
-        vscaleMax = vscaleMin;
-      return std::pair<unsigned, unsigned>(vscaleMin ? vscaleMin : 1,
-                                           vscaleMax);
-    }
+  if (langOpts.VScaleMin || langOpts.VScaleMax) {
+    // Treat Zvl*b as a lower bound on vscale.
+    vscaleMin = std::max(vscaleMin, langOpts.VScaleMin);
+    unsigned vscaleMax = langOpts.VScaleMax;
+    if (vscaleMax != 0 && vscaleMax < vscaleMin)
+      vscaleMax = vscaleMin;
+    return std::pair<unsigned, unsigned>(vscaleMin ? vscaleMin : 1, vscaleMax);
+  }
 
-    if (vscaleMin > 0) {
-      unsigned vscaleMax = isaInfo->getMaxVLen() / llvm::RISCV::RVVBitsPerBlock;
-      return std::make_pair(vscaleMin, vscaleMax);
-    }
-  } else {
-    if (langOpts.VScaleMin || langOpts.VScaleMax)
-      return std::pair<unsigned, unsigned>(
-          langOpts.VScaleMin ? langOpts.VScaleMin : 1, langOpts.VScaleMax);
+  if (vscaleMin > 0) {
+    unsigned vscaleMax = isaInfo->getMaxVLen() / llvm::RISCV::RVVBitsPerBlock;
+    return std::make_pair(vscaleMin, vscaleMax);
   }
 
   return std::nullopt;
 }
 
+// TODO: We should get this from TargetInfo. However, that depends on
+// too much of clang, so for now, replicate the functionality.
+static std::optional<std::pair<unsigned, unsigned>>
+getVScaleRange(CompilerInstance &ci) {
+  const auto &langOpts = ci.getInvocation().getLangOpts();
+  const llvm::Triple triple(ci.getInvocation().getTargetOpts().triple);
+
+  if (triple.isAArch64())
+    return getAArch64VScaleRange(ci);
+  if (triple.isRISCV())
+    return getRISCVVScaleRange(ci);
+
+  if (langOpts.VScaleMin || langOpts.VScaleMax)
+    return std::pair<unsigned, unsigned>(
+        langOpts.VScaleMin ? langOpts.VScaleMin : 1, langOpts.VScaleMax);
+
+  return std::nullopt;
+}
+
 // Lower the previously generated MLIR module into an LLVM IR module
 void CodeGenAction::generateLLVMIR() {
   assert(mlirModule && "The MLIR module has not been generated yet.");



More information about the flang-commits mailing list