brintos

brintos / llvm-project-archived public Read only

0
0
Text · 10.5 KiB · 321c092 Raw
276 lines · cpp
1//===- llvm/unittest/CodeGen/SPIRVAPITest.cpp -----------------------------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8//9/// \file10/// Test that SPIR-V Backend provides an API call that translates LLVM IR Module11/// into SPIR-V.12//13//===----------------------------------------------------------------------===//14 15#include "llvm/AsmParser/Parser.h"16#include "llvm/BinaryFormat/Magic.h"17#include "llvm/IR/Module.h"18#include "llvm/Support/SourceMgr.h"19#include "llvm/TargetParser/Triple.h"20#include "gtest/gtest.h"21#include <gmock/gmock.h>22#include <string>23 24namespace llvm {25 26extern "C" LLVM_EXTERNAL_VISIBILITY bool27SPIRVTranslate(Module *M, std::string &SpirvObj, std::string &ErrMsg,28               const std::vector<std::string> &AllowExtNames,29               llvm::CodeGenOptLevel OLevel, Triple TargetTriple);30 31extern "C" bool32SPIRVTranslateModule(Module *M, std::string &SpirvObj, std::string &ErrMsg,33                     const std::vector<std::string> &AllowExtNames,34                     const std::vector<std::string> &Opts);35 36class SPIRVAPITest : public testing::Test {37protected:38  bool toSpirv(StringRef Assembly, std::string &Result, std::string &ErrMsg,39               const std::vector<std::string> &AllowExtNames,40               llvm::CodeGenOptLevel OLevel, Triple TargetTriple) {41    SMDiagnostic ParseError;42    LLVMContext Context;43    std::unique_ptr<Module> M =44        parseAssemblyString(Assembly, ParseError, Context);45    if (!M) {46      ParseError.print("IR parsing failed: ", errs());47      report_fatal_error("Can't parse input assembly.");48    }49    bool Status = SPIRVTranslate(M.get(), Result, ErrMsg, AllowExtNames, OLevel,50                                 TargetTriple);51    if (!Status)52      errs() << ErrMsg;53    return Status;54  }55  // TODO: Remove toSpirvLegacy() and related tests after existing clients56  // switch into a newer implementation of SPIRVTranslate().57  bool toSpirvLegacy(StringRef Assembly, std::string &Result,58                     std::string &ErrMsg,59                     const std::vector<std::string> &AllowExtNames,60                     const std::vector<std::string> &Opts) {61    SMDiagnostic ParseError;62    LLVMContext Context;63    std::unique_ptr<Module> M =64        parseAssemblyString(Assembly, ParseError, Context);65    if (!M) {66      ParseError.print("IR parsing failed: ", errs());67      report_fatal_error("Can't parse input assembly.");68    }69    bool Status =70        SPIRVTranslateModule(M.get(), Result, ErrMsg, AllowExtNames, Opts);71    if (!Status)72      errs() << ErrMsg;73    return Status;74  }75 76  static constexpr StringRef ExtensionAssembly = R"(77    define dso_local spir_func void @test1() {78    entry:79      %res1 = tail call spir_func i32 @_Z26__spirv_GroupBitwiseAndKHR(i32 2, i32 0, i32 0)80      ret void81    }82 83    declare dso_local spir_func i32  @_Z26__spirv_GroupBitwiseAndKHR(i32, i32, i32)84  )";85  static constexpr StringRef OkAssembly = R"(86    %struct = type { [1 x i64] }87 88    define spir_kernel void @foo(ptr noundef byval(%struct) %arg) {89    entry:90      call spir_func void @bar(<2 x i32> noundef <i32 0, i32 1>)91      ret void92    }93 94    define spir_func void @bar(<2 x i32> noundef) {95    entry:96      ret void97    }98  )";99};100 101TEST_F(SPIRVAPITest, checkTranslateOk) {102  StringRef Assemblies[] = {"", OkAssembly};103  for (StringRef &Assembly : Assemblies) {104    std::string Result, Error;105    bool Status = toSpirv(Assembly, Result, Error, {}, CodeGenOptLevel::Default,106                          Triple("spirv32-unknown-unknown"));107    EXPECT_TRUE(Status && Error.empty() && !Result.empty());108    EXPECT_EQ(identify_magic(Result), file_magic::spirv_object);109  }110}111 112TEST_F(SPIRVAPITest, checkTranslateSupportExtensionByArg) {113  std::string Result, Error;114  std::vector<std::string> ExtNames{"SPV_KHR_uniform_group_instructions"};115  bool Status =116      toSpirv(ExtensionAssembly, Result, Error, ExtNames,117              CodeGenOptLevel::Aggressive, Triple("spirv64-unknown-unknown"));118  EXPECT_TRUE(Status && Error.empty() && !Result.empty());119  EXPECT_EQ(identify_magic(Result), file_magic::spirv_object);120}121 122TEST_F(SPIRVAPITest, checkTranslateSupportExtensionByArgList) {123  std::string Result, Error;124  std::vector<std::string> ExtNames{"SPV_KHR_subgroup_rotate",125                                    "SPV_KHR_uniform_group_instructions",126                                    "SPV_KHR_subgroup_rotate"};127  bool Status =128      toSpirv(ExtensionAssembly, Result, Error, ExtNames,129              CodeGenOptLevel::Aggressive, Triple("spirv64-unknown-unknown"));130  EXPECT_TRUE(Status && Error.empty() && !Result.empty());131  EXPECT_EQ(identify_magic(Result), file_magic::spirv_object);132}133 134TEST_F(SPIRVAPITest, checkTranslateAllExtensions) {135  std::string Result, Error;136  std::vector<std::string> ExtNames{"all"};137  bool Status =138      toSpirv(ExtensionAssembly, Result, Error, ExtNames,139              CodeGenOptLevel::Aggressive, Triple("spirv64-unknown-unknown"));140  EXPECT_TRUE(Status && Error.empty() && !Result.empty());141  EXPECT_EQ(identify_magic(Result), file_magic::spirv_object);142}143 144TEST_F(SPIRVAPITest, checkTranslateUnknownExtensionByArg) {145  std::string Result, Error;146  std::vector<std::string> ExtNames{"SPV_XYZ_my_unknown_extension"};147  bool Status =148      toSpirv(ExtensionAssembly, Result, Error, ExtNames,149              CodeGenOptLevel::Aggressive, Triple("spirv64-unknown-unknown"));150  EXPECT_FALSE(Status);151  EXPECT_TRUE(Result.empty());152  EXPECT_EQ(Error, "Unknown SPIR-V extension: SPV_XYZ_my_unknown_extension");153}154 155#if !defined(NDEBUG) && GTEST_HAS_DEATH_TEST156TEST_F(SPIRVAPITest, checkTranslateExtensionError) {157  std::string Result, Error;158  EXPECT_DEATH_IF_SUPPORTED(159      {160        toSpirv(ExtensionAssembly, Result, Error, {},161                CodeGenOptLevel::Aggressive, Triple("spirv64-unknown-unknown"));162      },163      "LLVM ERROR: __spirv_GroupBitwiseAndKHR: the builtin requires the "164      "following SPIR-V extension: SPV_KHR_uniform_group_instructions");165}166 167TEST_F(SPIRVAPITest, checkTranslateWrongExtensionByArg) {168  std::string Result, Error;169  std::vector<std::string> ExtNames{"SPV_KHR_subgroup_rotate"};170  EXPECT_DEATH_IF_SUPPORTED(171      {172        toSpirv(ExtensionAssembly, Result, Error, ExtNames,173                CodeGenOptLevel::Aggressive, Triple("spirv64-unknown-unknown"));174      },175      "LLVM ERROR: __spirv_GroupBitwiseAndKHR: the builtin requires the "176      "following SPIR-V extension: SPV_KHR_uniform_group_instructions");177}178#endif179 180// Legacy API calls. TODO: Remove after transition into a newer API.181TEST_F(SPIRVAPITest, checkTranslateStringOptsOk) {182  StringRef Assemblies[] = {"", OkAssembly};183  std::vector<std::string> SetOfOpts[] = {{}, {"spirv32-unknown-unknown"}};184  for (const auto &Opts : SetOfOpts) {185    for (StringRef &Assembly : Assemblies) {186      std::string Result, Error;187      bool Status = toSpirvLegacy(Assembly, Result, Error, {}, Opts);188      EXPECT_TRUE(Status && Error.empty() && !Result.empty());189      EXPECT_EQ(identify_magic(Result), file_magic::spirv_object);190    }191  }192}193 194TEST_F(SPIRVAPITest, checkTranslateStringOptsError) {195  std::string Result, Error;196  bool Status = toSpirvLegacy(OkAssembly, Result, Error, {},197                              {"spirv64v1.6-unknown-unknown", "5"});198  EXPECT_FALSE(Status);199  EXPECT_TRUE(Result.empty());200  EXPECT_EQ(Error, "Invalid optimization level!");201}202 203TEST_F(SPIRVAPITest, checkTranslateStringOptsErrorOk) {204  {205    std::string Result, Error;206    bool Status = toSpirvLegacy(OkAssembly, Result, Error, {},207                                {"spirv64v1.6-unknown-unknown", "5"});208    EXPECT_FALSE(Status);209    EXPECT_TRUE(Result.empty());210    EXPECT_EQ(Error, "Invalid optimization level!");211  }212  {213    std::string Result, Error;214    bool Status = toSpirvLegacy(OkAssembly, Result, Error, {},215                                {"spirv64v1.6-unknown-unknown", "3"});216    EXPECT_TRUE(Status && Error.empty() && !Result.empty());217    EXPECT_EQ(identify_magic(Result), file_magic::spirv_object);218  }219}220 221TEST_F(SPIRVAPITest, checkTranslateStringOptsSupportExtensionByArg) {222  std::string Result, Error;223  std::vector<std::string> ExtNames{"SPV_KHR_uniform_group_instructions"};224  bool Status = toSpirvLegacy(ExtensionAssembly, Result, Error, ExtNames, {});225  EXPECT_TRUE(Status && Error.empty() && !Result.empty());226  EXPECT_EQ(identify_magic(Result), file_magic::spirv_object);227}228 229TEST_F(SPIRVAPITest, checkTranslateStringOptsSupportExtensionByArgList) {230  std::string Result, Error;231  std::vector<std::string> ExtNames{"SPV_KHR_subgroup_rotate",232                                    "SPV_KHR_uniform_group_instructions",233                                    "SPV_KHR_subgroup_rotate"};234  bool Status = toSpirvLegacy(ExtensionAssembly, Result, Error, ExtNames, {});235  EXPECT_TRUE(Status && Error.empty() && !Result.empty());236  EXPECT_EQ(identify_magic(Result), file_magic::spirv_object);237}238 239TEST_F(SPIRVAPITest, checkTranslateStringOptsAllExtensions) {240  std::string Result, Error;241  std::vector<std::string> ExtNames{"all"};242  bool Status = toSpirvLegacy(ExtensionAssembly, Result, Error, ExtNames, {});243  EXPECT_TRUE(Status && Error.empty() && !Result.empty());244  EXPECT_EQ(identify_magic(Result), file_magic::spirv_object);245}246 247TEST_F(SPIRVAPITest, checkTranslateStringOptsUnknownExtensionByArg) {248  std::string Result, Error;249  std::vector<std::string> ExtNames{"SPV_XYZ_my_unknown_extension"};250  bool Status = toSpirvLegacy(ExtensionAssembly, Result, Error, ExtNames, {});251  EXPECT_FALSE(Status);252  EXPECT_TRUE(Result.empty());253  EXPECT_EQ(Error, "Unknown SPIR-V extension: SPV_XYZ_my_unknown_extension");254}255 256#if !defined(NDEBUG) && GTEST_HAS_DEATH_TEST257TEST_F(SPIRVAPITest, checkTranslateStringOptsExtensionError) {258  std::string Result, Error;259  EXPECT_DEATH_IF_SUPPORTED(260      { toSpirvLegacy(ExtensionAssembly, Result, Error, {}, {}); },261      "LLVM ERROR: __spirv_GroupBitwiseAndKHR: the builtin requires the "262      "following SPIR-V extension: SPV_KHR_uniform_group_instructions");263}264 265TEST_F(SPIRVAPITest, checkTranslateStringOptsWrongExtensionByArg) {266  std::string Result, Error;267  std::vector<std::string> ExtNames{"SPV_KHR_subgroup_rotate"};268  EXPECT_DEATH_IF_SUPPORTED(269      { toSpirvLegacy(ExtensionAssembly, Result, Error, ExtNames, {}); },270      "LLVM ERROR: __spirv_GroupBitwiseAndKHR: the builtin requires the "271      "following SPIR-V extension: SPV_KHR_uniform_group_instructions");272}273#endif274 275} // end namespace llvm276