mirror of
https://github.com/Kitware/CMake.git
synced 2026-07-15 12:00:51 +00:00
ISPC: Support generation for multiple instruction sets
This commit is contained in:
@@ -259,6 +259,7 @@ Properties on Targets
|
||||
/prop_tgt/INTERPROCEDURAL_OPTIMIZATION
|
||||
/prop_tgt/IOS_INSTALL_COMBINED
|
||||
/prop_tgt/ISPC_HEADER_DIRECTORY
|
||||
/prop_tgt/ISPC_INSTRUCTION_SETS
|
||||
/prop_tgt/JOB_POOL_COMPILE
|
||||
/prop_tgt/JOB_POOL_LINK
|
||||
/prop_tgt/JOB_POOL_PRECOMPILE_HEADER
|
||||
|
||||
@@ -512,6 +512,7 @@ Variables for Languages
|
||||
/variable/CMAKE_Fortran_MODDIR_FLAG
|
||||
/variable/CMAKE_Fortran_MODOUT_FLAG
|
||||
/variable/CMAKE_ISPC_HEADER_DIRECTORY
|
||||
/variable/CMAKE_ISPC_INSTRUCTION_SETS
|
||||
/variable/CMAKE_LANG_ANDROID_TOOLCHAIN_MACHINE
|
||||
/variable/CMAKE_LANG_ANDROID_TOOLCHAIN_PREFIX
|
||||
/variable/CMAKE_LANG_ANDROID_TOOLCHAIN_SUFFIX
|
||||
|
||||
21
Help/prop_tgt/ISPC_INSTRUCTION_SETS.rst
Normal file
21
Help/prop_tgt/ISPC_INSTRUCTION_SETS.rst
Normal file
@@ -0,0 +1,21 @@
|
||||
ISPC_INSTRUCTION_SETS
|
||||
---------------------
|
||||
|
||||
.. versionadded:: 3.19
|
||||
|
||||
List of instruction set architectures to generate code for.
|
||||
|
||||
This property is initialized by the value of the :variable:`CMAKE_ISPC_INSTRUCTION_SETS`
|
||||
variable if it is set when a target is created.
|
||||
|
||||
The ``ISPC_INSTRUCTION_SETS`` target property must be used when generating for multiple
|
||||
instruction sets so that CMake can track what object files will be generated.
|
||||
|
||||
Examples
|
||||
^^^^^^^^
|
||||
|
||||
.. code-block:: cmake
|
||||
|
||||
set_property(TARGET tgt PROPERTY ISPC_INSTRUCTION_SETS avx2-i32x4 avx512skx-i32x835)
|
||||
|
||||
Generates code for avx2 and avx512skx target architectures.
|
||||
9
Help/variable/CMAKE_ISPC_INSTRUCTION_SETS.rst
Normal file
9
Help/variable/CMAKE_ISPC_INSTRUCTION_SETS.rst
Normal file
@@ -0,0 +1,9 @@
|
||||
CMAKE_ISPC_INSTRUCTION_SETS
|
||||
---------------------------
|
||||
|
||||
.. versionadded:: 3.19
|
||||
|
||||
Default value for :prop_tgt:`ISPC_INSTRUCTION_SETS` property of targets.
|
||||
|
||||
This variable is used to initialize the :prop_tgt:`ISPC_INSTRUCTION_SETS` property
|
||||
on all targets. See the target property for additional information.
|
||||
@@ -200,6 +200,7 @@ SETUP_LANGUAGE(swift_properties, Swift);
|
||||
std::string const kCMAKE_CUDA_ARCHITECTURES = "CMAKE_CUDA_ARCHITECTURES";
|
||||
std::string const kCMAKE_CUDA_RUNTIME_LIBRARY = "CMAKE_CUDA_RUNTIME_LIBRARY";
|
||||
std::string const kCMAKE_ENABLE_EXPORTS = "CMAKE_ENABLE_EXPORTS";
|
||||
std::string const kCMAKE_ISPC_INSTRUCTION_SETS = "CMAKE_ISPC_INSTRUCTION_SETS";
|
||||
std::string const kCMAKE_LINK_SEARCH_END_STATIC =
|
||||
"CMAKE_LINK_SEARCH_END_STATIC";
|
||||
std::string const kCMAKE_LINK_SEARCH_START_STATIC =
|
||||
@@ -716,6 +717,7 @@ int cmCoreTryCompile::TryCompileCode(std::vector<std::string> const& argv,
|
||||
vars.insert(kCMAKE_CUDA_ARCHITECTURES);
|
||||
vars.insert(kCMAKE_CUDA_RUNTIME_LIBRARY);
|
||||
vars.insert(kCMAKE_ENABLE_EXPORTS);
|
||||
vars.insert(kCMAKE_ISPC_INSTRUCTION_SETS);
|
||||
vars.insert(kCMAKE_LINK_SEARCH_END_STATIC);
|
||||
vars.insert(kCMAKE_LINK_SEARCH_START_STATIC);
|
||||
vars.insert(kCMAKE_OSX_ARCHITECTURES);
|
||||
|
||||
@@ -3302,6 +3302,27 @@ void cmGeneratorTarget::AddCUDAArchitectureFlags(std::string& flags) const
|
||||
}
|
||||
}
|
||||
|
||||
void cmGeneratorTarget::AddISPCTargetFlags(std::string& flags) const
|
||||
{
|
||||
const std::string& property = this->GetSafeProperty("ISPC_INSTRUCTION_SETS");
|
||||
|
||||
// If ISPC_TARGET is false we don't add any architectures.
|
||||
if (cmIsOff(property)) {
|
||||
return;
|
||||
}
|
||||
|
||||
std::string const& compiler =
|
||||
this->Makefile->GetSafeDefinition("CMAKE_ISPC_COMPILER_ID");
|
||||
|
||||
if (compiler == "Intel") {
|
||||
std::vector<std::string> targets;
|
||||
cmExpandList(property, targets);
|
||||
if (!targets.empty()) {
|
||||
flags += cmStrCat(" --target=", cmWrap("", targets, "", ","));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void cmGeneratorTarget::AddCUDAToolkitFlags(std::string& flags) const
|
||||
{
|
||||
std::string const& compiler =
|
||||
@@ -5071,6 +5092,11 @@ void cmGeneratorTarget::GetTargetObjectNames(
|
||||
assert(!map_it->second.empty());
|
||||
objects.push_back(map_it->second);
|
||||
}
|
||||
|
||||
auto ispcObjects = this->GetGeneratedISPCObjects(config);
|
||||
for (std::string const& output : ispcObjects) {
|
||||
objects.push_back(cmSystemTools::GetFilenameName(output));
|
||||
}
|
||||
}
|
||||
|
||||
bool cmGeneratorTarget::StrictTargetComparison::operator()(
|
||||
@@ -6042,6 +6068,35 @@ std::vector<std::string> cmGeneratorTarget::GetGeneratedISPCHeaders(
|
||||
return iter->second;
|
||||
}
|
||||
|
||||
void cmGeneratorTarget::AddISPCGeneratedObject(std::vector<std::string>&& objs,
|
||||
std::string const& config)
|
||||
{
|
||||
std::string config_upper;
|
||||
if (!config.empty()) {
|
||||
config_upper = cmSystemTools::UpperCase(config);
|
||||
}
|
||||
auto iter = this->ISPCGeneratedObjects.find(config_upper);
|
||||
if (iter == this->ISPCGeneratedObjects.end()) {
|
||||
this->ISPCGeneratedObjects.insert({ config_upper, objs });
|
||||
} else {
|
||||
iter->second.insert(iter->second.end(), objs.begin(), objs.end());
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<std::string> cmGeneratorTarget::GetGeneratedISPCObjects(
|
||||
std::string const& config) const
|
||||
{
|
||||
std::string config_upper;
|
||||
if (!config.empty()) {
|
||||
config_upper = cmSystemTools::UpperCase(config);
|
||||
}
|
||||
auto iter = this->ISPCGeneratedObjects.find(config_upper);
|
||||
if (iter == this->ISPCGeneratedObjects.end()) {
|
||||
return std::vector<std::string>{};
|
||||
}
|
||||
return iter->second;
|
||||
}
|
||||
|
||||
std::string cmGeneratorTarget::GetFrameworkVersion() const
|
||||
{
|
||||
assert(this->GetType() != cmStateEnums::INTERFACE_LIBRARY);
|
||||
|
||||
@@ -449,6 +449,8 @@ public:
|
||||
void AddCUDAArchitectureFlags(std::string& flags) const;
|
||||
void AddCUDAToolkitFlags(std::string& flags) const;
|
||||
|
||||
void AddISPCTargetFlags(std::string& flags) const;
|
||||
|
||||
std::string GetFeatureSpecificLinkRuleVariable(
|
||||
std::string const& var, std::string const& lang,
|
||||
std::string const& config) const;
|
||||
@@ -821,6 +823,11 @@ public:
|
||||
std::vector<std::string> GetGeneratedISPCHeaders(
|
||||
std::string const& config) const;
|
||||
|
||||
void AddISPCGeneratedObject(std::vector<std::string>&& objs,
|
||||
std::string const& config);
|
||||
std::vector<std::string> GetGeneratedISPCObjects(
|
||||
std::string const& config) const;
|
||||
|
||||
private:
|
||||
void AddSourceCommon(const std::string& src, bool before = false);
|
||||
|
||||
@@ -1001,6 +1008,8 @@ private:
|
||||
|
||||
std::unordered_map<std::string, std::vector<std::string>>
|
||||
ISPCGeneratedHeaders;
|
||||
std::unordered_map<std::string, std::vector<std::string>>
|
||||
ISPCGeneratedObjects;
|
||||
|
||||
bool IsLinkLookupScope(std::string const& n,
|
||||
cmLocalGenerator const*& lg) const;
|
||||
|
||||
@@ -1165,6 +1165,12 @@ void cmGlobalNinjaGenerator::AppendTargetDepends(
|
||||
gg->MapToNinjaPath());
|
||||
outputDeps.insert(outputDeps.end(), headers.begin(), headers.end());
|
||||
}
|
||||
auto objs = depTarget->GetGeneratedISPCObjects(targetConfig);
|
||||
if (!objs.empty()) {
|
||||
std::transform(objs.begin(), objs.end(), objs.begin(),
|
||||
gg->MapToNinjaPath());
|
||||
outputDeps.insert(outputDeps.end(), objs.begin(), objs.end());
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -1966,6 +1966,8 @@ void cmLocalGenerator::AddLanguageFlags(std::string& flags,
|
||||
"See CMake issue #20726.");
|
||||
}
|
||||
}
|
||||
} else if (lang == "ISPC") {
|
||||
target->AddISPCTargetFlags(flags);
|
||||
}
|
||||
// Add VFS Overlay for Clang compiliers
|
||||
if (compiler == "Clang") {
|
||||
@@ -2428,7 +2430,17 @@ void cmLocalGenerator::AppendFlagEscape(std::string& flags,
|
||||
|
||||
void cmLocalGenerator::AddISPCDependencies(cmGeneratorTarget* target)
|
||||
{
|
||||
//
|
||||
std::vector<std::string> enabledLanguages =
|
||||
this->GetState()->GetEnabledLanguages();
|
||||
if (std::find(enabledLanguages.begin(), enabledLanguages.end(), "ISPC") ==
|
||||
enabledLanguages.end()) {
|
||||
return;
|
||||
}
|
||||
|
||||
std::vector<std::string> ispcSuffixes =
|
||||
detail::ComputeISPCObjectSuffixes(target);
|
||||
const bool extra_objects = (ispcSuffixes.size() > 1);
|
||||
|
||||
std::vector<std::string> configsList =
|
||||
this->Makefile->GetGeneratorConfigs(cmMakefile::IncludeEmptyConfig);
|
||||
for (std::string const& config : configsList) {
|
||||
@@ -2442,7 +2454,8 @@ void cmLocalGenerator::AddISPCDependencies(cmGeneratorTarget* target)
|
||||
std::vector<cmSourceFile*> sources;
|
||||
target->GetSourceFiles(sources, config);
|
||||
|
||||
// build up the list of ispc headers that this target is generating
|
||||
// build up the list of ispc headers and extra objects that this target is
|
||||
// generating
|
||||
for (cmSourceFile const* sf : sources) {
|
||||
// Generate this object file's rule file.
|
||||
const std::string& lang = sf->GetLanguage();
|
||||
@@ -2453,6 +2466,11 @@ void cmLocalGenerator::AddISPCDependencies(cmGeneratorTarget* target)
|
||||
|
||||
auto headerPath = cmStrCat(perConfigDir, '/', ispcSource, ".h");
|
||||
target->AddISPCGeneratedHeader(headerPath, config);
|
||||
if (extra_objects) {
|
||||
std::vector<std::string> objs = detail::ComputeISPCExtraObjects(
|
||||
objectName, perConfigDir, ispcSuffixes);
|
||||
target->AddISPCGeneratedObject(std::move(objs), config);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -4028,4 +4046,44 @@ void AddUtilityCommand(cmLocalGenerator& lg, const cmListFileBacktrace& lfbt,
|
||||
target->AddSource(force.NameCMP0049);
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<std::string> ComputeISPCObjectSuffixes(cmGeneratorTarget* target)
|
||||
{
|
||||
const std::string& targetProperty =
|
||||
target->GetSafeProperty("ISPC_INSTRUCTION_SETS");
|
||||
std::vector<std::string> ispcTargets;
|
||||
|
||||
if (!cmIsOff(targetProperty)) {
|
||||
cmExpandList(targetProperty, ispcTargets);
|
||||
for (auto& ispcTarget : ispcTargets) {
|
||||
// transform targets into the suffixes
|
||||
auto pos = ispcTarget.find('-');
|
||||
auto target_suffix = ispcTarget.substr(0, pos);
|
||||
if (target_suffix ==
|
||||
"avx1") { // when targetting avx1 ISPC uses the 'avx' output string
|
||||
target_suffix = "avx";
|
||||
}
|
||||
ispcTarget = target_suffix;
|
||||
}
|
||||
}
|
||||
return ispcTargets;
|
||||
}
|
||||
|
||||
std::vector<std::string> ComputeISPCExtraObjects(
|
||||
std::string const& objectName, std::string const& buildDirectory,
|
||||
std::vector<std::string> const& ispcSuffixes)
|
||||
{
|
||||
std::vector<std::string> computedObjects;
|
||||
computedObjects.reserve(ispcSuffixes.size());
|
||||
|
||||
auto extension = cmSystemTools::GetFilenameLastExtension(objectName);
|
||||
auto objNameNoExt =
|
||||
cmSystemTools::GetFilenameWithoutLastExtension(objectName);
|
||||
for (const auto& ispcTarget : ispcSuffixes) {
|
||||
computedObjects.emplace_back(
|
||||
cmStrCat(buildDirectory, "/", objNameNoExt, "_", ispcTarget, extension));
|
||||
}
|
||||
|
||||
return computedObjects;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -595,6 +595,11 @@ void AddUtilityCommand(cmLocalGenerator& lg, const cmListFileBacktrace& lfbt,
|
||||
bool escapeOldStyle, const char* comment,
|
||||
bool uses_terminal, bool command_expand_lists,
|
||||
const std::string& job_pool, bool stdPipesUTF8);
|
||||
|
||||
std::vector<std::string> ComputeISPCObjectSuffixes(cmGeneratorTarget* target);
|
||||
std::vector<std::string> ComputeISPCExtraObjects(
|
||||
std::string const& objectName, std::string const& buildDirectory,
|
||||
std::vector<std::string> const& ispcSuffixes);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -197,6 +197,17 @@ void cmMakefileTargetGenerator::WriteTargetBuildRules()
|
||||
}
|
||||
}
|
||||
|
||||
std::string currentBinDir =
|
||||
this->LocalGenerator->GetCurrentBinaryDirectory();
|
||||
|
||||
// Look for ISPC extra object files generated by this target
|
||||
auto ispcAdditionalObjs =
|
||||
this->GeneratorTarget->GetGeneratedISPCObjects(this->GetConfigName());
|
||||
for (std::string const& ispcObj : ispcAdditionalObjs) {
|
||||
this->CleanFiles.insert(this->LocalGenerator->MaybeConvertToRelativePath(
|
||||
currentBinDir, ispcObj));
|
||||
}
|
||||
|
||||
// add custom commands to the clean rules?
|
||||
bool clean = cmIsOff(this->Makefile->GetProperty("CLEAN_NO_CUSTOM"));
|
||||
|
||||
@@ -205,8 +216,6 @@ void cmMakefileTargetGenerator::WriteTargetBuildRules()
|
||||
std::vector<cmSourceFile const*> customCommands;
|
||||
this->GeneratorTarget->GetCustomCommands(customCommands,
|
||||
this->GetConfigName());
|
||||
std::string currentBinDir =
|
||||
this->LocalGenerator->GetCurrentBinaryDirectory();
|
||||
for (cmSourceFile const* sf : customCommands) {
|
||||
cmCustomCommandGenerator ccg(*sf->GetCustomCommand(),
|
||||
this->GetConfigName(), this->LocalGenerator);
|
||||
@@ -1494,6 +1503,11 @@ void cmMakefileTargetGenerator::WriteObjectsStrings(
|
||||
for (std::string const& obj : this->ExternalObjects) {
|
||||
helper.Feed(obj);
|
||||
}
|
||||
auto ispcAdditionalObjs =
|
||||
this->GeneratorTarget->GetGeneratedISPCObjects(this->GetConfigName());
|
||||
for (std::string const& obj : ispcAdditionalObjs) {
|
||||
helper.Feed(obj);
|
||||
}
|
||||
helper.Done();
|
||||
}
|
||||
|
||||
|
||||
@@ -911,11 +911,16 @@ void cmNinjaNormalTargetGenerator::WriteLinkStatement(
|
||||
linkBuild.ExplicitDeps.push_back(
|
||||
this->ConvertToNinjaPath(this->GetSourceFilePath(source)));
|
||||
}
|
||||
|
||||
linkBuild.Outputs.push_back(vars["SWIFT_MODULE"]);
|
||||
} else {
|
||||
linkBuild.ExplicitDeps = this->GetObjects(config);
|
||||
}
|
||||
|
||||
std::vector<std::string> extraISPCObjects =
|
||||
this->GetGeneratorTarget()->GetGeneratedISPCObjects(config);
|
||||
std::transform(extraISPCObjects.begin(), extraISPCObjects.end(),
|
||||
std::back_inserter(linkBuild.ExplicitDeps), MapToNinjaPath());
|
||||
|
||||
linkBuild.ImplicitDeps =
|
||||
this->ComputeLinkDeps(this->TargetLinkLanguage(config), config);
|
||||
|
||||
|
||||
@@ -1398,6 +1398,19 @@ void cmNinjaTargetGenerator::WriteObjectBuildStatement(
|
||||
// Make sure ninja knows how to clean the generated header
|
||||
this->GetGlobalGenerator()->AddAdditionalCleanFile(ispcHeader, config);
|
||||
|
||||
auto ispcSuffixes =
|
||||
detail::ComputeISPCObjectSuffixes(this->GeneratorTarget);
|
||||
if (ispcSuffixes.size() > 1) {
|
||||
auto ispcSideEfffectObjects = detail::ComputeISPCExtraObjects(
|
||||
objectName, ispcDirectory, ispcSuffixes);
|
||||
|
||||
for (auto sideEffect : ispcSideEfffectObjects) {
|
||||
sideEffect = this->ConvertToNinjaPath(sideEffect);
|
||||
objBuild.ImplicitOuts.emplace_back(sideEffect);
|
||||
this->GetGlobalGenerator()->AddAdditionalCleanFile(sideEffect, config);
|
||||
}
|
||||
}
|
||||
|
||||
vars["ISPC_HEADER_FILE"] =
|
||||
this->GetLocalGenerator()->ConvertToOutputFormat(
|
||||
ispcHeader, cmOutputConverter::SHELL);
|
||||
|
||||
@@ -369,6 +369,7 @@ cmTarget::cmTarget(std::string const& name, cmStateEnums::TargetType type,
|
||||
initProp("JOB_POOL_PRECOMPILE_HEADER");
|
||||
initProp("ISPC_COMPILER_LAUNCHER");
|
||||
initProp("ISPC_HEADER_DIRECTORY");
|
||||
initProp("ISPC_INSTRUCTION_SETS");
|
||||
initProp("LINK_SEARCH_START_STATIC");
|
||||
initProp("LINK_SEARCH_END_STATIC");
|
||||
initProp("Swift_LANGUAGE_VERSION");
|
||||
|
||||
@@ -6,7 +6,10 @@ macro (add_ispc_test_macro name)
|
||||
PROPERTY LABELS "ISPC")
|
||||
endmacro ()
|
||||
|
||||
add_ispc_test_macro(ISPC.ChainedStaticLibraries ISPCChainedStaticLibraries)
|
||||
add_ispc_test_macro(ISPC.Defines ISPCDefines)
|
||||
add_ispc_test_macro(ISPC.DynamicLibrary ISPCDynamicLibrary)
|
||||
add_ispc_test_macro(ISPC.ObjectGenex ISPCObjectGenex)
|
||||
add_ispc_test_macro(ISPC.ObjectLibrary ISPCObjectLibrary)
|
||||
add_ispc_test_macro(ISPC.ResponseAndDefine ISPCResponseAndDefine)
|
||||
add_ispc_test_macro(ISPC.StaticLibrary ISPCStaticLibrary)
|
||||
|
||||
22
Tests/ISPC/ChainedStaticLibraries/CMakeLists.txt
Normal file
22
Tests/ISPC/ChainedStaticLibraries/CMakeLists.txt
Normal file
@@ -0,0 +1,22 @@
|
||||
|
||||
cmake_minimum_required(VERSION 3.18)
|
||||
project(ISPCChainedStaticLibraries CXX ISPC)
|
||||
|
||||
if(CMAKE_SIZEOF_VOID_P EQUAL 4)
|
||||
set(CMAKE_ISPC_FLAGS "--arch=x86")
|
||||
endif()
|
||||
|
||||
|
||||
add_library(ispc_objects1 STATIC extra.ispc extra.cxx)
|
||||
add_library(ispc_objects2 STATIC simple.ispc)
|
||||
|
||||
set_target_properties(ispc_objects1 PROPERTIES POSITION_INDEPENDENT_CODE ON)
|
||||
set_target_properties(ispc_objects1 PROPERTIES ISPC_INSTRUCTION_SETS "avx1-i32x16;avx2-i32x4")
|
||||
|
||||
set_target_properties(ispc_objects2 PROPERTIES POSITION_INDEPENDENT_CODE ON)
|
||||
set_target_properties(ispc_objects2 PROPERTIES ISPC_INSTRUCTION_SETS "avx1-i32x16")
|
||||
|
||||
target_link_libraries(ispc_objects2 PRIVATE ispc_objects1)
|
||||
|
||||
add_executable(ISPCChainedStaticLibraries main.cxx)
|
||||
target_link_libraries(ISPCChainedStaticLibraries PUBLIC ispc_objects2)
|
||||
17
Tests/ISPC/ChainedStaticLibraries/extra.cxx
Normal file
17
Tests/ISPC/ChainedStaticLibraries/extra.cxx
Normal file
@@ -0,0 +1,17 @@
|
||||
#include <stdio.h>
|
||||
|
||||
#include "extra.ispc.h"
|
||||
|
||||
int extra()
|
||||
{
|
||||
float vin[16], vout[16];
|
||||
for (int i = 0; i < 16; ++i)
|
||||
vin[i] = i;
|
||||
|
||||
ispc::extra(vin, vout, 16);
|
||||
|
||||
for (int i = 0; i < 16; ++i)
|
||||
printf("%d: extra(%f) = %f\n", i, vin[i], vout[i]);
|
||||
|
||||
return 0;
|
||||
}
|
||||
12
Tests/ISPC/ChainedStaticLibraries/extra.ispc
Normal file
12
Tests/ISPC/ChainedStaticLibraries/extra.ispc
Normal file
@@ -0,0 +1,12 @@
|
||||
|
||||
export void extra(uniform float vin[], uniform float vout[],
|
||||
uniform int count) {
|
||||
foreach (index = 0 ... count) {
|
||||
float v = vin[index];
|
||||
if (v < 3.)
|
||||
v = v * v;
|
||||
else
|
||||
v = sqrt(v);
|
||||
vout[index] = v;
|
||||
}
|
||||
}
|
||||
15
Tests/ISPC/ChainedStaticLibraries/main.cxx
Normal file
15
Tests/ISPC/ChainedStaticLibraries/main.cxx
Normal file
@@ -0,0 +1,15 @@
|
||||
#include <stdio.h>
|
||||
|
||||
#include "simple.ispc.h"
|
||||
|
||||
int main()
|
||||
{
|
||||
float vin[16], vout[16];
|
||||
for (int i = 0; i < 16; ++i)
|
||||
vin[i] = i;
|
||||
|
||||
ispc::simple(vin, vout, 16);
|
||||
|
||||
for (int i = 0; i < 16; ++i)
|
||||
printf("%d: simple(%f) = %f\n", i, vin[i], vout[i]);
|
||||
}
|
||||
12
Tests/ISPC/ChainedStaticLibraries/simple.ispc
Normal file
12
Tests/ISPC/ChainedStaticLibraries/simple.ispc
Normal file
@@ -0,0 +1,12 @@
|
||||
|
||||
export void simple(uniform float vin[], uniform float vout[],
|
||||
uniform int count) {
|
||||
foreach (index = 0 ... count) {
|
||||
float v = vin[index];
|
||||
if (v < 3.)
|
||||
v = v * v;
|
||||
else
|
||||
v = sqrt(v);
|
||||
vout[index] = v;
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,7 @@
|
||||
cmake_minimum_required(VERSION 3.18)
|
||||
project(ISPCDefines CXX ISPC)
|
||||
|
||||
set(CMAKE_ISPC_INSTRUCTION_SETS "sse2-i32x4;sse4-i16x8;avx1-i32x16;avx2-i32x4;avx512knl-i32x16;avx512skx-i32x8")
|
||||
set(CMAKE_ISPC_FLAGS -DM_PI=3.1415926535f)
|
||||
add_compile_definitions([==[STRUCT_DEFINE=struct{uniform int a]==])
|
||||
|
||||
|
||||
20
Tests/ISPC/DynamicLibrary/CMakeLists.txt
Normal file
20
Tests/ISPC/DynamicLibrary/CMakeLists.txt
Normal file
@@ -0,0 +1,20 @@
|
||||
|
||||
cmake_minimum_required(VERSION 3.18)
|
||||
project(ISPCDynamicLibrary CXX ISPC)
|
||||
|
||||
if(CMAKE_SIZEOF_VOID_P EQUAL 4)
|
||||
set(CMAKE_ISPC_FLAGS "--arch=x86")
|
||||
endif()
|
||||
|
||||
|
||||
add_library(ispc_objects1 STATIC extra.ispc extra.cxx)
|
||||
add_library(ispc_objects2 SHARED simple.ispc)
|
||||
|
||||
set_target_properties(ispc_objects1 PROPERTIES POSITION_INDEPENDENT_CODE ON)
|
||||
set_target_properties(ispc_objects1 PROPERTIES ISPC_INSTRUCTION_SETS "avx1-i32x16;avx2-i32x4")
|
||||
set_target_properties(ispc_objects2 PROPERTIES ISPC_INSTRUCTION_SETS "avx1-i32x16")
|
||||
|
||||
target_link_libraries(ispc_objects2 PRIVATE ispc_objects1)
|
||||
|
||||
add_executable(ISPCDynamicLibrary main.cxx)
|
||||
target_link_libraries(ISPCDynamicLibrary PUBLIC ispc_objects2)
|
||||
17
Tests/ISPC/DynamicLibrary/extra.cxx
Normal file
17
Tests/ISPC/DynamicLibrary/extra.cxx
Normal file
@@ -0,0 +1,17 @@
|
||||
#include <stdio.h>
|
||||
|
||||
#include "extra.ispc.h"
|
||||
|
||||
int extra()
|
||||
{
|
||||
float vin[16], vout[16];
|
||||
for (int i = 0; i < 16; ++i)
|
||||
vin[i] = i;
|
||||
|
||||
ispc::extra(vin, vout, 16);
|
||||
|
||||
for (int i = 0; i < 16; ++i)
|
||||
printf("%d: extra(%f) = %f\n", i, vin[i], vout[i]);
|
||||
|
||||
return 0;
|
||||
}
|
||||
12
Tests/ISPC/DynamicLibrary/extra.ispc
Normal file
12
Tests/ISPC/DynamicLibrary/extra.ispc
Normal file
@@ -0,0 +1,12 @@
|
||||
|
||||
export void extra(uniform float vin[], uniform float vout[],
|
||||
uniform int count) {
|
||||
foreach (index = 0 ... count) {
|
||||
float v = vin[index];
|
||||
if (v < 3.)
|
||||
v = v * v;
|
||||
else
|
||||
v = sqrt(v);
|
||||
vout[index] = v;
|
||||
}
|
||||
}
|
||||
15
Tests/ISPC/DynamicLibrary/main.cxx
Normal file
15
Tests/ISPC/DynamicLibrary/main.cxx
Normal file
@@ -0,0 +1,15 @@
|
||||
#include <stdio.h>
|
||||
|
||||
#include "simple.ispc.h"
|
||||
|
||||
int main()
|
||||
{
|
||||
float vin[16], vout[16];
|
||||
for (int i = 0; i < 16; ++i)
|
||||
vin[i] = i;
|
||||
|
||||
ispc::simple(vin, vout, 16);
|
||||
|
||||
for (int i = 0; i < 16; ++i)
|
||||
printf("%d: simple(%f) = %f\n", i, vin[i], vout[i]);
|
||||
}
|
||||
12
Tests/ISPC/DynamicLibrary/simple.ispc
Normal file
12
Tests/ISPC/DynamicLibrary/simple.ispc
Normal file
@@ -0,0 +1,12 @@
|
||||
|
||||
export void simple(uniform float vin[], uniform float vout[],
|
||||
uniform int count) {
|
||||
foreach (index = 0 ... count) {
|
||||
float v = vin[index];
|
||||
if (v < 3.)
|
||||
v = v * v;
|
||||
else
|
||||
v = sqrt(v);
|
||||
vout[index] = v;
|
||||
}
|
||||
}
|
||||
45
Tests/ISPC/ObjectGenex/CMakeLists.txt
Normal file
45
Tests/ISPC/ObjectGenex/CMakeLists.txt
Normal file
@@ -0,0 +1,45 @@
|
||||
cmake_minimum_required(VERSION 3.18)
|
||||
project(ISPCObjectGenex CXX ISPC)
|
||||
|
||||
set(CMAKE_ISPC_INSTRUCTION_SETS "sse2-i32x4;sse4-i16x8;avx1-i32x16;avx2-i32x4;avx512knl-i32x16;avx512skx-i32x8")
|
||||
|
||||
add_library(ispc_objects OBJECT
|
||||
simple.ispc
|
||||
)
|
||||
target_compile_definitions(ispc_objects PRIVATE
|
||||
$<$<COMPILE_LANG_AND_ID:ISPC,Intel>:M_PI=3.1415926535f>
|
||||
)
|
||||
set_target_properties(ispc_objects PROPERTIES POSITION_INDEPENDENT_CODE ON)
|
||||
if(CMAKE_SIZEOF_VOID_P EQUAL 4)
|
||||
set_source_files_properties(simple.ispc PROPERTIES COMPILE_OPTIONS "--arch=x86")
|
||||
endif()
|
||||
|
||||
|
||||
#Test ObjectFiles with file(GENERATE)
|
||||
file(GENERATE
|
||||
OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/gen_$<LOWER_CASE:$<CONFIG>/>path_to_objs.h
|
||||
CONTENT [[
|
||||
#ifndef path_to_objs
|
||||
#define path_to_objs
|
||||
|
||||
#include <string>
|
||||
|
||||
static std::string obj_paths = "$<TARGET_OBJECTS:ispc_objects>";
|
||||
|
||||
#endif
|
||||
|
||||
]]
|
||||
)
|
||||
|
||||
|
||||
add_executable(ISPCObjectGenex main.cxx)
|
||||
add_dependencies(ISPCObjectGenex ispc_objects)
|
||||
|
||||
list(LENGTH CMAKE_ISPC_INSTRUCTION_SETS numberOfTargets)
|
||||
math(EXPR numberOfTargets "${numberOfTargets}+1")
|
||||
target_compile_definitions(ISPCObjectGenex PRIVATE
|
||||
"ExpectedISPCObjects=${numberOfTargets}"
|
||||
"CONFIG_TYPE=gen_$<LOWER_CASE:$<CONFIG>>"
|
||||
)
|
||||
target_include_directories(ISPCObjectGenex PRIVATE ${CMAKE_CURRENT_BINARY_DIR} )
|
||||
target_compile_features(ISPCObjectGenex PRIVATE cxx_std_11)
|
||||
87
Tests/ISPC/ObjectGenex/main.cxx
Normal file
87
Tests/ISPC/ObjectGenex/main.cxx
Normal file
@@ -0,0 +1,87 @@
|
||||
#include <stdio.h>
|
||||
|
||||
/*
|
||||
Define GENERATED_HEADER macro to allow c++ files to include headers
|
||||
generated based on different configuration types.
|
||||
*/
|
||||
|
||||
/* clang-format off */
|
||||
#define GENERATED_HEADER(x) GENERATED_HEADER0(CONFIG_TYPE/x)
|
||||
/* clang-format on */
|
||||
#define GENERATED_HEADER0(x) GENERATED_HEADER1(x)
|
||||
#define GENERATED_HEADER1(x) <x>
|
||||
|
||||
#include GENERATED_HEADER(path_to_objs.h)
|
||||
|
||||
#include <vector>
|
||||
std::vector<std::string> expandList(std::string const& arg)
|
||||
{
|
||||
std::vector<std::string> output;
|
||||
// If argument is empty or no `;` just copy the current string
|
||||
if (arg.empty() || arg.find(';') == std::string::npos) {
|
||||
output.emplace_back(arg);
|
||||
return output;
|
||||
}
|
||||
|
||||
std::string newArg;
|
||||
// Break the string at non-escaped semicolons not nested in [].
|
||||
int squareNesting = 0;
|
||||
auto last = arg.begin();
|
||||
auto const cend = arg.end();
|
||||
for (auto c = last; c != cend; ++c) {
|
||||
switch (*c) {
|
||||
case '\\': {
|
||||
// We only want to allow escaping of semicolons. Other
|
||||
// escapes should not be processed here.
|
||||
auto cnext = c + 1;
|
||||
if ((cnext != cend) && *cnext == ';') {
|
||||
newArg.append(last, c);
|
||||
// Skip over the escape character
|
||||
last = cnext;
|
||||
c = cnext;
|
||||
}
|
||||
} break;
|
||||
case '[': {
|
||||
++squareNesting;
|
||||
} break;
|
||||
case ']': {
|
||||
--squareNesting;
|
||||
} break;
|
||||
case ';': {
|
||||
// Break the string here if we are not nested inside square
|
||||
// brackets.
|
||||
if (squareNesting == 0) {
|
||||
newArg.append(last, c);
|
||||
// Skip over the semicolon
|
||||
last = c + 1;
|
||||
if (!newArg.empty()) {
|
||||
// Add the last argument if the string is not empty.
|
||||
output.push_back(newArg);
|
||||
newArg.clear();
|
||||
}
|
||||
}
|
||||
} break;
|
||||
default: {
|
||||
// Just append this character.
|
||||
} break;
|
||||
}
|
||||
}
|
||||
newArg.append(last, cend);
|
||||
if (!newArg.empty()) {
|
||||
// Add the last argument if the string is not empty.
|
||||
output.push_back(std::move(newArg));
|
||||
}
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
// determine that the number of object files specified in obj_paths
|
||||
// is equal to the number of arch's
|
||||
|
||||
std::vector<std::string> paths = expandList(obj_paths);
|
||||
const bool correctSize = (paths.size() == ExpectedISPCObjects);
|
||||
|
||||
return (correctSize) ? 0 : 1;
|
||||
}
|
||||
12
Tests/ISPC/ObjectGenex/simple.ispc
Normal file
12
Tests/ISPC/ObjectGenex/simple.ispc
Normal file
@@ -0,0 +1,12 @@
|
||||
|
||||
export void simple(uniform float vin[], uniform float vout[],
|
||||
uniform int count) {
|
||||
foreach (index = 0 ... count) {
|
||||
float v = vin[index];
|
||||
if (v < M_PI)
|
||||
v = v * v;
|
||||
else
|
||||
v = sqrt(v);
|
||||
vout[index] = v;
|
||||
}
|
||||
}
|
||||
@@ -7,11 +7,12 @@ if(CMAKE_SIZEOF_VOID_P EQUAL 4)
|
||||
set(CMAKE_ISPC_FLAGS "--arch=x86")
|
||||
endif()
|
||||
|
||||
|
||||
add_library(ispc_objects OBJECT simple.ispc extra.ispc)
|
||||
|
||||
target_compile_options(ispc_objects PRIVATE "$<$<COMPILE_LANGUAGE:ISPC>:--target=sse2-i32x4>")
|
||||
|
||||
set_target_properties(ispc_objects PROPERTIES POSITION_INDEPENDENT_CODE ON)
|
||||
set_target_properties(ispc_objects PROPERTIES ISPC_INSTRUCTION_SETS "sse2-i32x4;sse4-i8x16")
|
||||
|
||||
|
||||
add_executable(ISPCObjectLibrary main.cxx extra.cxx)
|
||||
target_link_libraries(ISPCObjectLibrary PRIVATE ispc_objects)
|
||||
|
||||
@@ -386,6 +386,7 @@ function(add_RunCMake_test_try_compile)
|
||||
CMAKE_CXX_COMPILER_VERSION
|
||||
CMAKE_CXX_STANDARD_DEFAULT
|
||||
CMake_TEST_CUDA
|
||||
CMake_TEST_ISPC
|
||||
CMake_TEST_FILESYSTEM_1S
|
||||
CMAKE_OBJC_STANDARD_DEFAULT
|
||||
CMAKE_OBJCXX_STANDARD_DEFAULT
|
||||
@@ -396,7 +397,7 @@ function(add_RunCMake_test_try_compile)
|
||||
endforeach()
|
||||
add_RunCMake_test(try_compile)
|
||||
set_property(TEST RunCMake.try_compile APPEND
|
||||
PROPERTY LABELS "CUDA")
|
||||
PROPERTY LABELS "CUDA;ISPC")
|
||||
endfunction()
|
||||
add_RunCMake_test_try_compile()
|
||||
|
||||
@@ -551,7 +552,10 @@ add_RunCMake_test(install -DNO_NAMELINK=${NO_NAMELINK} -DCYGWIN=${CYGWIN}
|
||||
-DCMAKE_SYSTEM_NAME=${CMAKE_SYSTEM_NAME}
|
||||
-DCMAKE_SHARED_LIBRARY_RUNTIME_C_FLAG=${CMAKE_SHARED_LIBRARY_RUNTIME_C_FLAG}
|
||||
-DCMAKE_EXECUTABLE_FORMAT=${CMAKE_EXECUTABLE_FORMAT}
|
||||
-DCMake_TEST_ISPC=${CMake_TEST_ISPC}
|
||||
)
|
||||
set_property(TEST RunCMake.install APPEND
|
||||
PROPERTY LABELS "ISPC")
|
||||
|
||||
add_RunCMake_test(file-GET_RUNTIME_DEPENDENCIES
|
||||
-DCMAKE_C_COMPILER_ID=${CMAKE_C_COMPILER_ID}
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
|
||||
set(objs obj1 obj2)
|
||||
set(targets sse2 sse4 avx avx2)
|
||||
foreach(o IN LISTS objs)
|
||||
set(item "objs/${o}\\.ispc\\.(o|obj)")
|
||||
check_installed("${item}")
|
||||
foreach(t IN LISTS targets)
|
||||
set(item "objs/${o}\\.ispc_${t}\\.(o|obj)")
|
||||
check_installed("${item}")
|
||||
endforeach()
|
||||
endforeach()
|
||||
@@ -0,0 +1,4 @@
|
||||
enable_language(ISPC)
|
||||
add_library(objs OBJECT obj1.ispc obj2.ispc)
|
||||
set_target_properties(objs PROPERTIES ISPC_INSTRUCTION_SETS "sse2-i32x4;sse4-i16x8;avx1-i32x16;avx2-i32x4")
|
||||
install(FILES $<TARGET_OBJECTS:objs> DESTINATION objs)
|
||||
@@ -96,6 +96,11 @@ if(NOT RunCMake_GENERATOR STREQUAL "Xcode" OR NOT "$ENV{CMAKE_OSX_ARCHITECTURES}
|
||||
run_install_test(FILES-TARGET_OBJECTS)
|
||||
endif()
|
||||
|
||||
if(CMake_TEST_ISPC)
|
||||
run_install_test(FILES-EXTRA_ISPC_TARGET_OBJECTS)
|
||||
endif()
|
||||
|
||||
|
||||
run_install_test(TARGETS-InstallFromSubDir)
|
||||
run_install_test(TARGETS-OPTIONAL)
|
||||
run_install_test(FILES-OPTIONAL)
|
||||
|
||||
4
Tests/RunCMake/install/obj1.ispc
Normal file
4
Tests/RunCMake/install/obj1.ispc
Normal file
@@ -0,0 +1,4 @@
|
||||
|
||||
float func1(float a, float b) {
|
||||
return a + b / 2.;
|
||||
}
|
||||
4
Tests/RunCMake/install/obj2.ispc
Normal file
4
Tests/RunCMake/install/obj2.ispc
Normal file
@@ -0,0 +1,4 @@
|
||||
|
||||
float func2(float a, float b) {
|
||||
return a + b / 2.;
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
.*Error: Can't compile to multiple variants of avx512skx target!.*
|
||||
8
Tests/RunCMake/try_compile/ISPCDuplicateTarget.cmake
Normal file
8
Tests/RunCMake/try_compile/ISPCDuplicateTarget.cmake
Normal file
@@ -0,0 +1,8 @@
|
||||
enable_language(ISPC)
|
||||
set(CMAKE_ISPC_INSTRUCTION_SETS avx512skx-i32x16
|
||||
avx512skx-i32x16)
|
||||
try_compile(result ${CMAKE_CURRENT_BINARY_DIR}
|
||||
SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/src.ispc
|
||||
OUTPUT_VARIABLE out
|
||||
)
|
||||
message("try_compile output:\n${out}")
|
||||
@@ -0,0 +1 @@
|
||||
1
|
||||
@@ -0,0 +1 @@
|
||||
.*ninja: error: .* multiple rules generate.*src.ispc_avx512skx.o.*
|
||||
11
Tests/RunCMake/try_compile/ISPCDuplicateTargetNinja.cmake
Normal file
11
Tests/RunCMake/try_compile/ISPCDuplicateTargetNinja.cmake
Normal file
@@ -0,0 +1,11 @@
|
||||
enable_language(ISPC)
|
||||
set(CMAKE_ISPC_INSTRUCTION_SETS avx512skx-i32x16
|
||||
avx512skx-i32x16)
|
||||
try_compile(result ${CMAKE_CURRENT_BINARY_DIR}
|
||||
SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/src.ispc
|
||||
OUTPUT_VARIABLE out
|
||||
)
|
||||
message("try_compile output:\n${out}")
|
||||
if(NOT result)
|
||||
message(FATAL_ERROR "making Ninja and Ninja Multi-Config behave the same")
|
||||
endif()
|
||||
1
Tests/RunCMake/try_compile/ISPCInvalidTarget-stderr.txt
Normal file
1
Tests/RunCMake/try_compile/ISPCInvalidTarget-stderr.txt
Normal file
@@ -0,0 +1 @@
|
||||
.*Error: Incorrect targets: avxknl-i32x16.*
|
||||
7
Tests/RunCMake/try_compile/ISPCInvalidTarget.cmake
Normal file
7
Tests/RunCMake/try_compile/ISPCInvalidTarget.cmake
Normal file
@@ -0,0 +1,7 @@
|
||||
enable_language(ISPC)
|
||||
set(CMAKE_ISPC_INSTRUCTION_SETS "avxknl-i32x16")
|
||||
try_compile(result ${CMAKE_CURRENT_BINARY_DIR}
|
||||
SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/src.ispc
|
||||
OUTPUT_VARIABLE out
|
||||
)
|
||||
message("try_compile output:\n${out}")
|
||||
1
Tests/RunCMake/try_compile/ISPCTargets-stderr.txt
Normal file
1
Tests/RunCMake/try_compile/ISPCTargets-stderr.txt
Normal file
@@ -0,0 +1 @@
|
||||
.*Linking ISPC static library*
|
||||
1
Tests/RunCMake/try_compile/ISPCTargets-stdout.txt
Normal file
1
Tests/RunCMake/try_compile/ISPCTargets-stdout.txt
Normal file
@@ -0,0 +1 @@
|
||||
.*Detecting ISPC compiler ABI info - done.*
|
||||
7
Tests/RunCMake/try_compile/ISPCTargets.cmake
Normal file
7
Tests/RunCMake/try_compile/ISPCTargets.cmake
Normal file
@@ -0,0 +1,7 @@
|
||||
enable_language(ISPC)
|
||||
set(CMAKE_ISPC_INSTRUCTION_SETS avx512knl-i32x16 avx512skx-i32x16)
|
||||
try_compile(result ${CMAKE_CURRENT_BINARY_DIR}
|
||||
SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/src.ispc
|
||||
OUTPUT_VARIABLE out
|
||||
)
|
||||
message("try_compile output:\n${out}")
|
||||
@@ -51,6 +51,15 @@ endif()
|
||||
if(CMake_TEST_CUDA)
|
||||
run_cmake(CudaStandard)
|
||||
endif()
|
||||
if(CMake_TEST_ISPC)
|
||||
run_cmake(ISPCTargets)
|
||||
run_cmake(ISPCInvalidTarget)
|
||||
set(ninja "")
|
||||
if(RunCMake_GENERATOR MATCHES "Ninja")
|
||||
set(ninja "Ninja")
|
||||
endif()
|
||||
run_cmake(ISPCDuplicateTarget${ninja})
|
||||
endif()
|
||||
if(CMAKE_C_COMPILER_ID STREQUAL "GNU" AND NOT CMAKE_C_COMPILER_VERSION VERSION_LESS 4.4)
|
||||
run_cmake(CStandardGNU)
|
||||
endif()
|
||||
|
||||
4
Tests/RunCMake/try_compile/src.ispc
Normal file
4
Tests/RunCMake/try_compile/src.ispc
Normal file
@@ -0,0 +1,4 @@
|
||||
|
||||
float func(float a, float b) {
|
||||
return a + b / 2.;
|
||||
}
|
||||
Reference in New Issue
Block a user