diff --git a/flang/lib/Frontend/FrontendActions.cpp b/flang/lib/Frontend/FrontendActions.cpp index d4a3e164d2073..23bcab0676a8b 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 #include @@ -707,11 +709,10 @@ 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> -getVScaleRange(CompilerInstance &ci) { +getAArch64VScaleRange(CompilerInstance &ci) { const auto &langOpts = ci.getInvocation().getLangOpts(); + if (langOpts.VScaleMin || langOpts.VScaleMax) return std::pair( langOpts.VScaleMin ? langOpts.VScaleMin : 1, langOpts.VScaleMax); @@ -723,6 +724,66 @@ getVScaleRange(CompilerInstance &ci) { return std::nullopt; } +static std::optional> +getRISCVVScaleRange(CompilerInstance &ci) { + const auto &langOpts = ci.getInvocation().getLangOpts(); + const auto targetOpts = ci.getInvocation().getTargetOpts(); + const llvm::Triple triple(targetOpts.triple); + + 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(); + + // 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(vscaleMin ? vscaleMin : 1, 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> +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( + 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."); 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 b08ad91feb388..d7fc6ad0a62c3 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,26 @@ ! 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=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