Add Linux ppc64le (PowerPC64) architecture support using generic targets (#3735)

* Add Linux ppc64le (PowerPC64) architecture support using generic targets

Add ppc64le as a new architecture in ISPC, enabling compilation for
POWER8+ (POWER ISA 3.0) processors using the existing generic target
system (generic-i1x4 through generic-i64x4).

Key changes:
- Add Arch::ppc64le enum and parsing/serialization support
- Add CPU_PPC64LE_Generic device type with pwr8 baseline and +vsx features
- Initialize LLVM PowerPC backend when ISPC_PPC64_ENABLED is defined
- Generate ppc64le-linux-gnu triple for the target
- Auto-detect ppc64le host architecture and default to generic-i32x4
- Add PPC64_ENABLED CMake option (OFF by default) with powerpc LLVM component
- Add ppc64le support to builtin generation (GenerateBuiltins.cmake,
  GenericTargets.cmake, bitcode2cpp.py)
- Add PowerPC to LLVM_TARGETS_TO_BUILD in alloy.py and superbuild
- Add lit test infrastructure: PPC64_ENABLED feature flag, PPC64LE_HOST
  detection, and generic-target-ppc64le.ispc test
- Mark 5 tests UNSUPPORTED on PPC64LE_HOST due to known issues:
  gather/scatter assertion, LLVM selection failures, missing rcp stdlib,
  and ABI signext mismatch

Tested on Fedora 43 ppc64le (POWER8+) with LLVM 20: 425 tests passed,
267 unsupported, 3 expectedly failed, 0 failures.

* Add ppc64le to supported architectures in documentation

Update ispc.rst to list ppc64le in supported architectures and add
experimental PowerPC64 support entry to v1.31.0 release notes.

* Add ppc64le support to examples timing utility

Add __powerpc64__ to the architecture guard in timing.h so it uses
gettimeofday-based timing instead of x86 inline assembly (rdtsc/cpuid)
on PowerPC64 hosts.

* Add ppc64le support to example CMake build system

Add ppc64le architecture detection and generic target selection to the
example build system. On ppc64le, examples default to generic-i32x4
target. Also guard x86-specific -m32/-m64 compiler flags to only apply
on x86 architectures.

All 15 CPU examples build and pass on ppc64le.

* Fix generic-target build and ppc64le arch inference for cross-compilation

Fix missing build dependencies for the generic-target CMake OBJECT library:
- Add GENERATED property to generated CPP source files
- Add add_dependencies on generic-target-cpp and generic-stdlib-cpp targets
- Move configure_ispc_obj(generic-target) into add_ispc_slim() so include
  directories are set in both slim and composite binary paths

Fix lGetArchFromTarget to correctly infer ppc64le architecture when
cross-compiling with --cpu=ppc64le on non-PPC hosts. Previously the arch
inference was entirely host-guarded, causing it to fall through to x86_64.

* Address PR review: fix ppc64le triple, add test runner support and asm test

- Fix ppc64le LLVM triple to use canonical 'powerpc64le' prefix instead
  of 'ppc64le' in cmake/GenerateBuiltins.cmake
- Add ppc64le support to scripts/run_tests.py: target config, gcc_arch
  flags, and default target/arch detection for ppc64le hosts
- Add ppc64le-vector-asm.ispc lit test verifying PowerPC VSX vector
  instructions (xvaddsp, xvmulsp) are generated for generic targets

* Revert autoformatted changes

* Document reasons for ppc64le UNSUPPORTED test skips

Add explanatory comments to all lit tests marked UNSUPPORTED on ppc64le:
- stdlib-short-vec-funcs-3: LLVM 20 can't select froundeven for vectors
- stdlib-short-vec-funcs-6: LLVM 20 can't promote atan2/pow/fmod results
  Both are fixed in LLVM 21 (PR llvm/llvm-project#150597)
- fast_math_opt: generic target rcp uses fdiv, failing CHECK_NOFDIV
- num-limits: ABI mismatch for int8/int16 returns between ISPC and clang
- 2169: ISPC assertion in integer divide optimization for generic targets

* Make ppc64le LLVM bug test skips version-conditional

Use 'UNSUPPORTED: PPC64LE_HOST && !LLVM_21_0+' instead of unconditional
'UNSUPPORTED: PPC64LE_HOST' for tests that fail due to LLVM 20 PowerPC
backend bugs fixed in LLVM 21. This automatically re-enables the tests
when ISPC is built with LLVM 21+.

* s/UNSUPPORTED/XFAIL

* Add -mcpu

* Update docs

* Add PPC64 CI workflow with Ubuntu + QEMU for lit tests

* Fix check_isa to guard PPC64LE detection with endianness check

* Re-align with default target

* Revert all changes made to docs/ispc.rst

* Add functional tests to PPC64 CI workflow via QEMU

* Disable ispcrt build in PPC64 CI to avoid TBB dependency

* Install libtbb-dev instead of disabling ispcrt in PPC64 CI

* Disable X86 and ARM targets in PPC64 CI to avoid missing 32-bit headers

* Install gcc-multilib and re-enable all targets in PPC64 CI

* Install python3-dev for examples build in PPC64 CI

* Switch PPC64 CI to Ubuntu 25.10 with native LLVM 20 packages

* Fix LLVM tools package name to llvm-20-tools for Ubuntu 25.10

* Replace gcc-multilib with cross-compilation headers in PPC64 CI

Use libc6-dev-i386-cross and libc6-dev-armhf-cross instead of gcc-multilib
to provide 32-bit headers for builtin compilation. This avoids the package
conflict between gcc-multilib and gcc-powerpc64le-linux-gnu on Ubuntu 25.10.

* Add libstdc++-15-dev for host C++ linking in PPC64 CI

clang++ needs libstdc++-dev to link C++ programs on the host. Previously
gcc-multilib pulled this in as a dependency; now that we use cross packages
instead, we need to install it explicitly.

* Create FileCheck symlink for unversioned lookup in PPC64 CI

Ubuntu 25.10 installs FileCheck as FileCheck-20 (versioned), but ISPC's
CMake FindLLVM.cmake looks for the unversioned name. Create a symlink
to resolve this.

Tested locally: full build + lit tests pass in Ubuntu 25.10 Docker.

* Revert configure_ispc_obj(generic-target) move, no longer needed after #3739

* Fix PPC64 CI: build only PPC64 target, remove unnecessary cross-compilation packages

Disable ARM and x86 targets in the PPC64 CI workflow since they are
not needed and cause build failures due to missing cross-compilation
headers in the container. Also remove libc6-dev-i386-cross and
libc6-dev-armhf-cross packages that were only needed for those targets.

* Fix PPC64 CI: keep X86 enabled for host lit tests, remove build artifacts

Remove -DX86_ENABLED=OFF from the PPC64 CI cmake command since lit tests
use --target=host which detects x86 on the CI runner.

Remove set_source_files_properties and add_dependencies lines from
GenericTargets.cmake that were artifacts of the configure_ispc_obj move
reverted in c1a2b488.

* fix: Fix PPC64LE pipeline

* Add pipeline running on native runner

* Add sudo to apt-get install commands in workflow

* Consolidate pipelines

* Skip miscompiled float16 tests on ppc64le and fix native runner

- Add '// rule: skip on arch=ppc64le' to 54 float16/f16 functional tests
  that fail compilation on ppc64le
- Drop g++-multilib from native runner (unavailable on ppc64le)
- Add -DX86_ENABLED=OFF to native runner cmake to avoid x86 dependencies

* Refactor ppc64le arch inference out of lGetArchFromTarget

Revert lGetArchFromTarget to its original single-parameter signature and
move the cross-compilation arch fix-up for ppc64le to the call site.
This keeps the function focused on target-to-arch mapping and handles
the CPU-based override separately.

* Rename ppc64le CPU identifier to pwr8

Use 'pwr8' instead of 'ppc64le' as the CPU name for the generic PPC64LE
target, aligning the --cpu flag value with the actual LLVM CPU name that
was already being set internally.

* Skip float16 func tests on ppc64le due to missing fp16 support

* Install LLVM 19 packages for native ppc64le CI runner

* fix: clean up

* fix: install libclang-19-dev

* fix: s/generic/pwr8

* func-tests: skip round() varying float tests on ppc64le

LLVM PowerPC backend (POWER8) cannot lower @llvm.roundeven for vector
types (v4f32), which the generic builtin path uses for round(). Skip
these tests on ppc64le until a target-specific implementation is added.

* doc: clean up

* doc: move PowerPC support to new ISPC 1.31.0 section
This commit is contained in:
Trung Lê
2026-02-23 21:55:31 +00:00
committed by GitHub
parent c790edc266
commit b72df90271
93 changed files with 451 additions and 30 deletions
+109
View File
@@ -0,0 +1,109 @@
# Copyright 2026, Intel Corporation
# SPDX-License-Identifier: BSD-3-Clause
name: PowerPC64 Tests
permissions: read-all
on:
pull_request:
paths:
- 'src/**'
- 'builtins/**'
- 'cmake/**'
- 'CMakeLists.txt'
- '.github/workflows/ppc64.yml'
workflow_dispatch:
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
jobs:
ppc64-native-test:
name: PowerPC64LE generic-i32x4 test (native)
runs-on: ubuntu-24.04-ppc64le
steps:
- uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0
with:
submodules: true
- name: Install dependencies
run: |
sudo apt-get update
sudo apt-get install -y git curl cmake xz-utils m4 flex bison python3 python3-dev libtbb-dev \
llvm-19-dev clang-19 lld-19 libclang-19-dev
- name: Check tools
run: |
cmake --version
llvm-config-19 --version
clang-19 --version
gcc --version
g++ --version
- name: Build ISPC with PPC64 support
run: |
PATH=/usr/lib/llvm-19/bin:$PATH cmake -B build -DPPC64_ENABLED=ON -DARM_ENABLED=OFF -DX86_ENABLED=OFF
cmake --build build -j"$(nproc)"
- name: Run lit tests
run: |
cmake --build build --target check-all
- name: Run PPC64LE tests
run: |
PATH="$PWD"/build/bin:"$PATH" \
python3 scripts/run_tests.py \
--target=generic-i32x4 \
--arch=ppc64le \
--compiler=g++ \
-o O2
ppc64-cross-test:
name: PowerPC64LE generic-i32x4 test (cross-compiled)
runs-on: ubuntu-24.04
env:
LLVM_TAR: llvm-21.1.8-ubuntu22.04-Release+Asserts-x86.arm.ppc.wasm.tar.xz
steps:
- uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0
with:
submodules: true
- name: Install dependencies
run: |
.github/workflows/scripts/install-build-deps.sh
- name: Install PPC64 cross-compilation tools
run: |
sudo apt-get install -y gcc-powerpc64le-linux-gnu g++-powerpc64le-linux-gnu \
libc6-dev-ppc64el-cross qemu-user
- name: Check tools
run: |
cmake --version
llvm-config --version
clang --version
powerpc64le-linux-gnu-gcc --version
qemu-ppc64le --version
- name: Build ISPC with PPC64 support
run: |
cmake -B build -DPPC64_ENABLED=ON -DARM_ENABLED=OFF
cmake --build build -j"$(nproc)"
- name: Run lit tests
run: |
cmake --build build --target check-all
- name: Run PPC64LE tests
run: |
PATH="$PWD"/build/bin:"$PATH" \
python3 scripts/run_tests.py \
--target=generic-i32x4 \
--arch=ppc64le \
--wrap-exe="qemu-ppc64le" \
--compiler=powerpc64le-linux-gnu-g++ \
-o O2
+15 -2
View File
@@ -155,10 +155,16 @@ if (LLVM_TARGETS_BUILT MATCHES "RISCV")
set(LLVM_SUPPORTS_RISCV ON)
endif()
set(LLVM_SUPPORTS_PPC64 OFF)
if (LLVM_TARGETS_BUILT MATCHES "PowerPC")
set(LLVM_SUPPORTS_PPC64 ON)
endif()
option(X86_ENABLED "Enable x86 support" ${X86_HOST})
option(ARM_ENABLED "Enable ARM support" ${LLVM_SUPPORTS_ARM})
# Turn off RISC-V support by default. Later we can use ${LLVM_SUPPORTS_RISCV} for default option value.
option(RISCV_ENABLED "Enable RISC-V support" OFF)
option(PPC64_ENABLED "Enable PowerPC64 support" OFF)
option(WASM_ENABLED "Enable experimental Web Assembly support" OFF)
option(XE_ENABLED "Enable Intel Xe support" OFF)
@@ -370,8 +376,8 @@ find_package(FLEX 2.6 REQUIRED)
)
endif()
if (NOT X86_ENABLED AND NOT ARM_ENABLED AND NOT RISCV_ENABLED AND NOT WASM_ENABLED AND NOT XE_ENABLED)
message( FATAL_ERROR "Either X86, ARM, RISC-V, WASM or XE targets need to be enabled.")
if (NOT X86_ENABLED AND NOT ARM_ENABLED AND NOT RISCV_ENABLED AND NOT PPC64_ENABLED AND NOT WASM_ENABLED AND NOT XE_ENABLED)
message( FATAL_ERROR "Either X86, ARM, RISC-V, PowerPC64, WASM or XE targets need to be enabled.")
endif ()
# All possible ISPC targets
@@ -451,6 +457,9 @@ endif()
if (RISCV_ENABLED)
list(APPEND LLVM_COMPONENTS riscv)
endif()
if (PPC64_ENABLED)
list(APPEND LLVM_COMPONENTS powerpc)
endif()
if (WASM_ENABLED)
list(APPEND LLVM_COMPONENTS webassembly)
endif()
@@ -648,6 +657,10 @@ if (RISCV_ENABLED)
list(APPEND COMPILE_DEFINITIONS ISPC_RISCV_ENABLED)
endif()
if (PPC64_ENABLED)
list(APPEND COMPILE_DEFINITIONS ISPC_PPC64_ENABLED)
endif()
if (XE_ENABLED)
list(APPEND COMPILE_DEFINITIONS ISPC_XE_ENABLED)
endif()
+9
View File
@@ -200,6 +200,9 @@ function (get_target_flags os arch out)
elseif (${arch} STREQUAL "riscv64")
set(triple ${arch}-unknown-linux-gnu)
set(debian_triple ${arch}-linux-gnu)
elseif (${arch} STREQUAL "ppc64le")
set(triple powerpc64le-unknown-linux-gnu)
set(debian_triple powerpc64le-linux-gnu)
else()
message(FATAL_ERROR "Error")
endif()
@@ -300,6 +303,8 @@ function(builtin_to_cpp bit os generic_arch)
set(arch "aarch64")
elseif ("${bit}" STREQUAL "64" AND ${generic_arch} STREQUAL "riscv")
set(arch "riscv64")
elseif ("${bit}" STREQUAL "64" AND ${generic_arch} STREQUAL "ppc")
set(arch "ppc64le")
else()
message(FATAL_ERROR "Error")
endif()
@@ -431,6 +436,10 @@ function (generate_common_builtins)
builtin_to_cpp(64 linux riscv)
endif()
if (ISPC_LINUX_TARGET AND PPC64_ENABLED)
builtin_to_cpp(64 linux ppc)
endif()
if (ISPC_LINUX_TARGET AND X86_ENABLED)
builtin_to_cpp(32 linux x86)
builtin_to_cpp(64 linux x86)
+8 -2
View File
@@ -1,5 +1,5 @@
#
# Copyright (c) 2025, Intel Corporation
# Copyright (c) 2025-2026, Intel Corporation
#
# SPDX-License-Identifier: BSD-3-Clause
@@ -84,6 +84,12 @@ function (generate_generic_builtins ispc_name)
)
endif()
if (PPC64_ENABLED AND ISPC_LINUX_TARGET)
list(APPEND ARCH_LIST
"ppc64le,64"
)
endif()
foreach(os ${os_list})
foreach(target ${TARGET_LIST})
foreach(pair ${ARCH_LIST})
@@ -91,7 +97,7 @@ function (generate_generic_builtins ispc_name)
list(GET pair_split 0 arch)
list(GET pair_split 1 bit)
# Skip unsupported cases, see Target::GetTripleString for more details.
if (${os} STREQUAL "windows" AND (${arch} STREQUAL "arm" OR ${arch} STREQUAL "riscv64"))
if (${os} STREQUAL "windows" AND (${arch} STREQUAL "arm" OR ${arch} STREQUAL "riscv64" OR ${arch} STREQUAL "ppc64le"))
continue()
endif()
generate_generic_target_builtin(${ispc_name} ${target} ${arch} ${bit} ${os})
+12
View File
@@ -257,6 +257,18 @@ of recent changes to the compiler.
.. _ReleaseNotes.txt: https://raw.github.com/ispc/ispc/main/docs/ReleaseNotes.txt
Updating ISPC Programs For Changes In ISPC 1.31.0
-------------------------------------------------
New Architecture Support:
* Initial support for the PowerPC 64-bit little-endian (ppc64le) architecture
has been added using generic targets (e.g., generic-i32x4). The baseline is
POWER ISA 2.7 (POWER8+) with VSX. This support is experimental and not
included in official ISPC binaries. To use it, build ISPC from source with
the `PPC64_ENABLED=ON` CMake option. Usage: `ispc --arch=ppc64le
--target=generic-i32x4 foo.ispc -o foo.o`.
Updating ISPC Programs For Changes In ISPC 1.30.0
-------------------------------------------------
+3 -3
View File
@@ -1,12 +1,12 @@
/*
Copyright (c) 2010-2023, Intel Corporation
Copyright (c) 2010-2026, Intel Corporation
SPDX-License-Identifier: BSD-3-Clause
*/
#include <stdint.h>
#if defined(__arm__) || defined(__aarch64__)
#if defined(__arm__) || defined(__aarch64__) || defined(__powerpc64__)
#include <stddef.h>
#include <sys/time.h>
// There's no easy way to get a hardware clock counter on ARM, so instead
@@ -68,7 +68,7 @@ static inline double rtc(void) {
}
#endif // !WIN32
#endif // !__arm__ && !__aarch64__
#endif // !__arm__ && !__aarch64__ && !__powerpc64__
static uint64_t ustart, uend;
static double tstart, tend;
+3 -1
View File
@@ -1,5 +1,5 @@
#
# Copyright (c) 2018-2023, Intel Corporation
# Copyright (c) 2018-2026, Intel Corporation
#
# SPDX-License-Identifier: BSD-3-Clause
@@ -26,6 +26,8 @@ if (UNIX)
set(ispc_arch "arm")
elseif ("${ARCH}" STREQUAL "aarch64")
set(ispc_arch "aarch64")
elseif ("${ARCH}" STREQUAL "ppc64le")
set(ispc_arch "ppc64le")
endif()
endif()
+20 -6
View File
@@ -1,5 +1,5 @@
#
# Copyright (c) 2018-2025, Intel Corporation
# Copyright (c) 2018-2026, Intel Corporation
#
# SPDX-License-Identifier: BSD-3-Clause
@@ -9,7 +9,7 @@
function(add_ispc_example)
set(options USE_COMMON_SETTINGS)
set(oneValueArgs NAME ISPC_SRC_NAME DATA_DIR)
set(multiValueArgs ISPC_IA_TARGETS ISPC_ARM_TARGETS ISPC_FLAGS TARGET_SOURCES LIBRARIES DATA_FILES RUN_ARGS)
set(multiValueArgs ISPC_IA_TARGETS ISPC_ARM_TARGETS ISPC_PPC64LE_TARGETS ISPC_FLAGS TARGET_SOURCES LIBRARIES DATA_FILES RUN_ARGS)
cmake_parse_arguments("example" "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN} )
set(ISPC_KNOWN_TARGETS "sse2" "sse4" "avx1-" "avx2" "avx512skx" "neon")
@@ -41,6 +41,12 @@ function(add_ispc_example)
endif()
elseif ("${ISPC_ARCH}" STREQUAL "arm" OR "${ISPC_ARCH}" STREQUAL "aarch64")
set(ISPC_TARGETS ${example_ISPC_ARM_TARGETS})
elseif ("${ISPC_ARCH}" STREQUAL "ppc64le")
if (example_ISPC_PPC64LE_TARGETS)
set(ISPC_TARGETS ${example_ISPC_PPC64LE_TARGETS})
else()
set(ISPC_TARGETS "generic-i32x4")
endif()
else()
message(FATAL_ERROR "Unknown architecture ${ISPC_ARCH}")
endif()
@@ -49,6 +55,12 @@ function(add_ispc_example)
set(ISPC_TARGETS ${example_ISPC_IA_TARGETS})
elseif ("${ISPC_ARCH}" STREQUAL "arm" OR "${ISPC_ARCH}" STREQUAL "aarch64")
set(ISPC_TARGETS ${example_ISPC_ARM_TARGETS})
elseif ("${ISPC_ARCH}" STREQUAL "ppc64le")
if (example_ISPC_PPC64LE_TARGETS)
set(ISPC_TARGETS ${example_ISPC_PPC64LE_TARGETS})
else()
set(ISPC_TARGETS "generic-i32x4")
endif()
else()
message(FATAL_ERROR "Unknown architecture ${ISPC_ARCH}")
endif()
@@ -75,10 +87,12 @@ function(add_ispc_example)
# Compile options
set_property(TARGET ${example_NAME} PROPERTY POSITION_INDEPENDENT_CODE ON)
if (UNIX)
if (${ISPC_ARCH_BIT} EQUAL 32)
target_compile_options(${example_NAME} PRIVATE -m32)
else()
target_compile_options(${example_NAME} PRIVATE -m64)
if ("${ISPC_ARCH}" MATCHES "x86")
if (${ISPC_ARCH_BIT} EQUAL 32)
target_compile_options(${example_NAME} PRIVATE -m32)
else()
target_compile_options(${example_NAME} PRIVATE -m64)
endif()
endif()
else()
target_compile_options(${example_NAME} PRIVATE /fp:fast /Oi)
+12 -4
View File
@@ -1,5 +1,5 @@
#
# Copyright (c) 2018-2025, Intel Corporation
# Copyright (c) 2018-2026, Intel Corporation
#
# SPDX-License-Identifier: BSD-3-Clause
@@ -9,13 +9,19 @@
function(add_ispc_example)
set(options USE_COMMON_SETTINGS)
set(oneValueArgs NAME ISPC_SRC_NAME DATA_DIR)
set(multiValueArgs ISPC_IA_TARGETS ISPC_ARM_TARGETS ISPC_FLAGS TARGET_SOURCES LIBRARIES DATA_FILES RUN_ARGS)
set(multiValueArgs ISPC_IA_TARGETS ISPC_ARM_TARGETS ISPC_PPC64LE_TARGETS ISPC_FLAGS TARGET_SOURCES LIBRARIES DATA_FILES RUN_ARGS)
cmake_parse_arguments("example" "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN} )
if ("${ISPC_ARCH}" MATCHES "x86")
string(REPLACE "," ";" ISPC_TARGETS ${example_ISPC_IA_TARGETS})
elseif ("${ISPC_ARCH}" STREQUAL "arm" OR "${ISPC_ARCH}" STREQUAL "aarch64")
string(REPLACE "," ";" ISPC_TARGETS ${example_ISPC_ARM_TARGETS})
elseif ("${ISPC_ARCH}" STREQUAL "ppc64le")
if (example_ISPC_PPC64LE_TARGETS)
string(REPLACE "," ";" ISPC_TARGETS ${example_ISPC_PPC64LE_TARGETS})
else()
set(ISPC_TARGETS "generic-i32x4")
endif()
else()
message(FATAL_ERROR "Unknown architecture ${ISPC_ARCH}")
endif()
@@ -34,8 +40,10 @@ function(add_ispc_example)
target_compile_options(${example_NAME} PRIVATE $<$<COMPILE_LANGUAGE:ISPC>:--arch=${ISPC_ARCH}>)
if (UNIX)
set(arch_flag "-m${ISPC_ARCH_BIT}")
target_compile_options(${example_NAME} PRIVATE $<$<COMPILE_LANGUAGE:C,CXX>:${arch_flag}>)
if ("${ISPC_ARCH}" MATCHES "x86")
set(arch_flag "-m${ISPC_ARCH_BIT}")
target_compile_options(${example_NAME} PRIVATE $<$<COMPILE_LANGUAGE:C,CXX>:${arch_flag}>)
endif()
elseif (WIN32 AND MSVC)
target_compile_options(${example_NAME} PRIVATE $<$<COMPILE_LANGUAGE:C,CXX>:/fp:fast /Oi>)
endif()
+1 -1
View File
@@ -254,7 +254,7 @@ def build_LLVM(version_LLVM, folder, debug, selfbuild, extra, openmp, from_valid
try_do_LLVM("patch LLVM with patch " + patch, "git apply " + patch, from_validation, verbose)
os.chdir("../")
targets_and_common_options = r" -DLLVM_ENABLE_ZLIB=OFF -DLLVM_ENABLE_ZSTD=OFF -DLLVM_TARGETS_TO_BUILD=AArch64\;ARM\;RISCV\;X86 -DLLVM_EXPERIMENTAL_TARGETS_TO_BUILD=WebAssembly"
targets_and_common_options = r" -DLLVM_ENABLE_ZLIB=OFF -DLLVM_ENABLE_ZSTD=OFF -DLLVM_TARGETS_TO_BUILD=AArch64\;ARM\;PowerPC\;RISCV\;X86 -DLLVM_EXPERIMENTAL_TARGETS_TO_BUILD=WebAssembly"
# Build without terminfo support. Starting from 19.0 it's the default and the options is removed.
if version_LLVM < "19_0":
+4 -2
View File
@@ -1,6 +1,6 @@
#!/usr/bin/env python3
#
# Copyright (c) 2025, Intel Corporation
# Copyright (c) 2025-2026, Intel Corporation
#
# SPDX-License-Identifier: BSD-3-Clause
@@ -40,7 +40,7 @@ def bundle_header(src, output):
outfile.write("0x00 };\n\n")
outfile.write(f"int {name}_length = {length};\n")
ARCH_CHOICES = ['i686', 'x86', 'x86_64', 'arm', 'armv8a', 'arm64', 'riscv64', 'aarch64', 'wasm32', 'wasm64', 'xe64']
ARCH_CHOICES = ['i686', 'x86', 'x86_64', 'arm', 'armv8a', 'arm64', 'riscv64', 'ppc64le', 'aarch64', 'wasm32', 'wasm64', 'xe64']
parser = argparse.ArgumentParser()
parser.add_argument("src", help="Source file to process")
@@ -106,6 +106,8 @@ if args[0].arch in ARCH_CHOICES:
ispc_arch = "aarch64"
elif args[0].arch == "riscv64":
ispc_arch = "riscv64"
elif args[0].arch == "ppc64le":
ispc_arch = "ppc64le"
elif args[0].arch == "wasm32":
ispc_arch = "wasm32"
elif args[0].arch == "wasm64":
+10 -1
View File
@@ -1,6 +1,6 @@
#!/usr/bin/env python3
#
# Copyright (c) 2013-2025, Intel Corporation
# Copyright (c) 2013-2026, Intel Corporation
#
# SPDX-License-Identifier: BSD-3-Clause
@@ -111,6 +111,8 @@ class TargetConfig(object):
def set_target(self):
if self.target == 'neon':
self.arch = 'aarch64'
elif self.target.startswith('generic') and self.arch == 'ppc64le':
pass # arch is already set correctly
# Representation of output which goes to console.
# It consist of stdout & stderr.
@@ -659,6 +661,10 @@ def run_test(testname, host, target, jit_lib_path=None):
gcc_arch = '-march=rv64gcv'
if options.wrapexe and options.wrapexe.startswith('qemu'):
gcc_arch += ' -static'
elif target.arch == 'ppc64le':
gcc_arch = '-mcpu=power8'
if options.wrapexe and options.wrapexe.startswith('qemu'):
gcc_arch += ' -static'
elif target.arch == 'wasm64':
gcc_arch = '-sMEMORY64'
else:
@@ -1356,6 +1362,9 @@ elif platform.machine() == "aarch64":
elif platform.machine() == "arm64":
default_target = "neon-i32x4"
default_arch = "aarch64"
elif platform.machine() == "ppc64le":
default_target = "generic-i32x4"
default_arch = "ppc64le"
elif "86" in platform.machine() or platform.machine() == "AMD64":
# Some variant of x86: x86_64, i386, i486, i586, i686
# Windows reports platform as AMD64
+57
View File
@@ -65,6 +65,8 @@ Module *ispc::m;
#define ISPC_HOST_IS_ARM
#elif defined(__riscv)
#define ISPC_HOST_IS_RISCV
#elif defined(__powerpc64__) && (__BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__)
#define ISPC_HOST_IS_PPC64LE
#elif defined(__i386__) || defined(__x86_64__) || defined(_M_IX86) || defined(_M_X64)
#define ISPC_HOST_IS_X86
#endif
@@ -224,6 +226,8 @@ static ISPCTarget lGetSystemISA() {
return lGetARMSystemISA();
#elif defined(ISPC_HOST_IS_RISCV)
return ISPCTarget::rvv_x4;
#elif defined(ISPC_HOST_IS_PPC64LE)
return ISPCTarget::generic_i32x4;
#elif defined(ISPC_HOST_IS_X86)
enum Target::ISA isa = (enum Target::ISA)dispatch::get_x86_isa();
switch (isa) {
@@ -399,6 +403,9 @@ typedef enum {
CPU_SpacemiT_X60,
#endif // ISPC_LLVM_VERSION
#endif // ISPC_RISCV_ENABLED
#ifdef ISPC_PPC64_ENABLED
CPU_PPC64LE_Pwr8,
#endif
#ifdef ISPC_XE_ENABLED
GPU_TGLLP,
GPU_ACM_G10,
@@ -508,6 +515,9 @@ std::map<DeviceType, std::set<std::string>> CPUFeatures = {
{CPU_SpacemiT_X60, {}},
#endif // ISPC_LLVM_VERSION
#endif // ISPC_RISCV_ENABLED
#ifdef ISPC_PPC64_ENABLED
{CPU_PPC64LE_Pwr8, {}},
#endif
#ifdef ISPC_XE_ENABLED
{GPU_TGLLP, {}},
{GPU_ACM_G10, {}},
@@ -638,6 +648,10 @@ class AllCPUs {
#endif // ISPC_LLVM_VERSION
#endif // ISPC_RISCV_ENABLED
#ifdef ISPC_PPC64_ENABLED
names[CPU_PPC64LE_Pwr8].push_back("pwr8");
#endif
#ifdef ISPC_XE_ENABLED
names[GPU_TGLLP].push_back("tgllp");
names[GPU_TGLLP].push_back("dg1");
@@ -757,6 +771,10 @@ class AllCPUs {
#endif // ISPC_LLVM_VERSION
#endif // ISPC_RISCV_ENABLED
#ifdef ISPC_PPC64_ENABLED
compat[CPU_PPC64LE_Pwr8] = Set(CPU_PPC64LE_Pwr8, CPU_None);
#endif
#ifdef ISPC_XE_ENABLED
compat[GPU_TGLLP] = Set(GPU_TGLLP, CPU_None);
compat[GPU_ACM_G10] = Set(GPU_ACM_G10, GPU_ACM_G11, GPU_ACM_G12, GPU_TGLLP, CPU_None);
@@ -839,6 +857,13 @@ Arch lGetArchFromTarget(ISPCTarget target) {
return Arch::riscv64;
}
#endif
#ifdef ISPC_PPC64_ENABLED
if (ISPCTargetIsGeneric(target)) {
#if defined(ISPC_HOST_IS_PPC64LE)
return Arch::ppc64le;
#endif
}
#endif
#if ISPC_XE_ENABLED
if (ISPCTargetIsGen(target)) {
return Arch::xe64;
@@ -1005,6 +1030,12 @@ Target::Target(Arch arch, const char *cpu, ISPCTarget ispc_target, PICLevel picL
break;
#endif // ISPC_RISCV_ENABLED
#ifdef ISPC_PPC64_ENABLED
case CPU_PPC64LE_Pwr8:
m_ispc_target = ISPCTarget::generic_i32x4;
break;
#endif
#ifdef ISPC_XE_ENABLED
case GPU_TGLLP:
m_ispc_target = ISPCTarget::xelp_x16;
@@ -1111,6 +1142,15 @@ Target::Target(Arch arch, const char *cpu, ISPCTarget ispc_target, PICLevel picL
if (arch == Arch::none) {
arch = lGetArchFromTarget(m_ispc_target);
}
#ifdef ISPC_PPC64_ENABLED
// When cross-compiling for PPC64LE (e.g., --cpu=pwr8 on an x86 host),
// lGetArchFromTarget cannot infer the arch from a generic target alone.
// Fix up the arch based on the CPU identifier.
// TODO: add a proper PowerPC target
if (CPUID == CPU_PPC64LE_Pwr8) {
arch = Arch::ppc64le;
}
#endif
bool error = false;
// Make sure the target architecture is a known one; print an error
@@ -2141,6 +2181,12 @@ Target::Target(Arch arch, const char *cpu, ISPCTarget ispc_target, PICLevel picL
CPUID = CPU_x86_64;
cpu = a.GetDefaultNameFromType(CPUID).c_str();
}
#ifdef ISPC_PPC64_ENABLED
if (arch == Arch::ppc64le && ISPCTargetIsGeneric(m_ispc_target) && cpu_string.empty()) {
CPUID = CPU_PPC64LE_Pwr8;
cpu = a.GetDefaultNameFromType(CPUID).c_str();
}
#endif
} else {
if ((CPUfromISA != CPU_None) && !a.BackwardCompatible(CPUID, CPUfromISA)) {
std::string target_string = ISPCTargetToString(m_ispc_target);
@@ -2232,6 +2278,13 @@ Target::Target(Arch arch, const char *cpu, ISPCTarget ispc_target, PICLevel picL
m_cpu = "";
}
}
#endif
#ifdef ISPC_PPC64_ENABLED
if (arch == Arch::ppc64le) {
if (m_cpu == "pwr8") {
featuresString = "+vsx";
}
}
#endif
// Support 'i64' and 'double' types in cm
if (isXeTarget()) {
@@ -2516,6 +2569,8 @@ llvm::Triple Target::GetTriple() const {
triple.setArchName("aarch64");
} else if (m_arch == Arch::riscv64) {
triple.setArchName("riscv64");
} else if (m_arch == Arch::ppc64le) {
triple.setArchName("ppc64le");
} else if (m_arch == Arch::xe64) {
triple.setArchName("spir64");
} else {
@@ -2538,6 +2593,8 @@ llvm::Triple Target::GetTriple() const {
triple.setEnvironment(llvm::Triple::EnvironmentType::GNUEABIHF);
} else if (m_arch == Arch::riscv64) {
triple.setEnvironment(llvm::Triple::EnvironmentType::GNU);
} else if (m_arch == Arch::ppc64le) {
triple.setEnvironment(llvm::Triple::EnvironmentType::GNU);
} else {
Error(SourcePos(), "Unknown arch.");
exit(1);
+10 -1
View File
@@ -1,5 +1,5 @@
/*
Copyright (c) 2025, Intel Corporation
Copyright (c) 2025-2026, Intel Corporation
SPDX-License-Identifier: BSD-3-Clause
*/
@@ -509,6 +509,15 @@ bool Initialize() {
LLVMInitializeRISCVTargetMC();
#endif
#ifdef ISPC_PPC64_ENABLED
LLVMInitializePowerPCTargetInfo();
LLVMInitializePowerPCTarget();
LLVMInitializePowerPCAsmPrinter();
LLVMInitializePowerPCAsmParser();
LLVMInitializePowerPCDisassembler();
LLVMInitializePowerPCTargetMC();
#endif
#ifdef ISPC_WASM_ENABLED
LLVMInitializeWebAssemblyAsmParser();
LLVMInitializeWebAssemblyAsmPrinter();
+8 -2
View File
@@ -1,5 +1,5 @@
/*
Copyright (c) 2019-2025, Intel Corporation
Copyright (c) 2019-2026, Intel Corporation
SPDX-License-Identifier: BSD-3-Clause
*/
@@ -54,7 +54,9 @@ Arch operator++(Arch &arch, int dummy) {
"Enum Arch is not sequential");
static_assert(static_cast<underlying>(Arch::riscv64) == static_cast<underlying>(Arch::aarch64) + 1,
"Enum Arch is not sequential");
static_assert(static_cast<underlying>(Arch::wasm32) == static_cast<underlying>(Arch::riscv64) + 1,
static_assert(static_cast<underlying>(Arch::ppc64le) == static_cast<underlying>(Arch::riscv64) + 1,
"Enum Arch is not sequential");
static_assert(static_cast<underlying>(Arch::wasm32) == static_cast<underlying>(Arch::ppc64le) + 1,
"Enum Arch is not sequential");
static_assert(static_cast<underlying>(Arch::wasm64) == static_cast<underlying>(Arch::wasm32) + 1,
"Enum Arch is not sequential");
@@ -322,6 +324,8 @@ Arch ParseArch(std::string arch) {
return Arch::aarch64;
} else if (arch == "riscv64") {
return Arch::riscv64;
} else if (arch == "ppc64le") {
return Arch::ppc64le;
} else if (arch == "wasm32") {
return Arch::wasm32;
} else if (arch == "wasm64") {
@@ -346,6 +350,8 @@ std::string ArchToString(Arch arch) {
return "aarch64";
case Arch::riscv64:
return "riscv64";
case Arch::ppc64le:
return "ppc64le";
case Arch::wasm32:
return "wasm32";
case Arch::wasm64:
+2 -2
View File
@@ -1,5 +1,5 @@
/*
Copyright (c) 2019-2025, Intel Corporation
Copyright (c) 2019-2026, Intel Corporation
SPDX-License-Identifier: BSD-3-Clause
*/
@@ -26,7 +26,7 @@ std::string OSToString(TargetOS os);
std::string OSToLowerString(TargetOS os);
TargetOS GetHostOS();
enum class Arch { none, x86, x86_64, arm, aarch64, riscv64, wasm32, wasm64, xe64, error };
enum class Arch { none, x86, x86_64, arm, aarch64, riscv64, ppc64le, wasm32, wasm64, xe64, error };
Arch operator++(Arch &, int);
Arch ParseArch(std::string arch);
+1 -1
View File
@@ -585,7 +585,7 @@ endif()
# Targets to build.
# It is possible to build for stage1 only X86 if we build only on x86 platforms.
list(APPEND LLVM_COMMON_CMAKE_ARGS
-DLLVM_TARGETS_TO_BUILD=X86$<SEMICOLON>AArch64$<SEMICOLON>ARM$<SEMICOLON>RISCV
-DLLVM_TARGETS_TO_BUILD=X86$<SEMICOLON>AArch64$<SEMICOLON>ARM$<SEMICOLON>PowerPC$<SEMICOLON>RISCV
-DLLVM_EXPERIMENTAL_TARGETS_TO_BUILD=WebAssembly
)
+2 -1
View File
@@ -1,5 +1,5 @@
#
# Copyright (c) 2018-2025, Intel Corporation
# Copyright (c) 2018-2026, Intel Corporation
#
# SPDX-License-Identifier: BSD-3-Clause
@@ -22,6 +22,7 @@ list(APPEND LIT_ARGS "-Dispc_llvm_version_number=${LLVM_VERSION_NUMBER}")
list(APPEND LIT_ARGS "-Dx86_enabled=$<IF:$<BOOL:${X86_ENABLED}>,ON,OFF>")
list(APPEND LIT_ARGS "-Darm_enabled=$<IF:$<BOOL:${ARM_ENABLED}>,ON,OFF>")
list(APPEND LIT_ARGS "-Driscv_enabled=$<IF:$<BOOL:${RISCV_ENABLED}>,ON,OFF>")
list(APPEND LIT_ARGS "-Dppc64_enabled=$<IF:$<BOOL:${PPC64_ENABLED}>,ON,OFF>")
list(APPEND LIT_ARGS "-Dwasm_enabled=$<IF:$<BOOL:${WASM_ENABLED}>,ON,OFF>")
list(APPEND LIT_ARGS "-Dxe_enabled=$<IF:$<BOOL:${XE_ENABLED}>,ON,OFF>")
# ISPC enabled OS.
+1
View File
@@ -1,3 +1,4 @@
// rule: skip on arch=ppc64le
#include "test_static.isph"
task void f_f(uniform float RET[], uniform float aFOO[]) {
float16 a = aFOO[programIndex];
@@ -1,4 +1,5 @@
#include "test_static.isph"
// rule: skip on arch=ppc64le
task void f_f(uniform float RET[], uniform float aFOO[]) {
uniform float error = 0;
RET[programIndex] = 0;
@@ -1,6 +1,7 @@
#include "test_static.isph"
// rule: skip on arch=wasm32
// rule: skip on arch=wasm64
// rule: skip on arch=ppc64le
task void f_f(uniform float RET[], uniform float aFOO[]) {
float error = 0;
RET[programIndex] = 0;
@@ -1,4 +1,5 @@
#include "test_static.isph"
// rule: skip on arch=ppc64le
task void f_f(uniform float RET[], uniform float aFOO[]) {
float16 a = aFOO[programIndex];
RET[programIndex] = clamp((float16)3 * a, 5.f16, 10.f16);
@@ -1,3 +1,4 @@
// rule: skip on arch=ppc64le
#include "test_static.isph"
task void f_f(uniform float RET[], uniform float aFOO[]) {
RET[programIndex] = -1;
@@ -1,4 +1,5 @@
#include "test_static.isph"
// rule: skip on arch=ppc64le
uniform bool ok(uniform float16 x, uniform float16 ref) {
return (abs(x - ref) < 1e-2f16) || abs((x - ref) / ref) < 1e-1f16;
}
@@ -1,6 +1,7 @@
#include "test_static.isph"
// rule: skip on arch=wasm32
// rule: skip on arch=wasm64
// rule: skip on arch=ppc64le
bool ok(float16 x, float16 ref) { return (abs(x - ref) < 1e-2f16) || abs((x - ref) / ref) < 1e-1f16; }
task void f_fu(uniform float RET[], uniform float aFOO[], uniform float b) {
varying float16 arg = ((aFOO[programIndex] / programCount) * 2);
@@ -1,4 +1,5 @@
#include "test_static.isph"
// rule: skip on arch=ppc64le
task void f_f(uniform float RET[], uniform float aFOO[]) {
uniform float error = 0;
RET[programIndex] = 0;
@@ -1,6 +1,7 @@
#include "test_static.isph"
// rule: skip on arch=wasm32
// rule: skip on arch=wasm64
// rule: skip on arch=ppc64le
task void f_f(uniform float RET[], uniform float aFOO[]) {
float error = 0;
RET[programIndex] = 0;
@@ -1,4 +1,5 @@
#include "test_static.isph"
// rule: skip on arch=ppc64le
task void f_f(uniform float RET[], uniform float aFOO[]) {
RET[programIndex] = 0;
@@ -1,4 +1,5 @@
#include "test_static.isph"
// rule: skip on arch=ppc64le
task void f_f(uniform float RET[], uniform float aFOO[]) {
RET[programIndex] = 0;
+1
View File
@@ -1,4 +1,5 @@
#include "test_static.isph"
// rule: skip on arch=ppc64le
task void f_v(uniform float RET[]) {
float errors = 0;
for (uniform int i = -2; i <= 2; ++i) {
+1
View File
@@ -1,4 +1,5 @@
#include "test_static.isph"
// rule: skip on arch=ppc64le
task void f_f(uniform float RET[], uniform float aFOO[]) {
RET[programIndex] = 0.0f;
float16 testVal = ldexp(aFOO[0]-1, -2);
@@ -1,4 +1,5 @@
#include "test_static.isph"
// rule: skip on arch=ppc64le
uniform bool ok(uniform float16 x, uniform float16 ref) {
return (abs(x - ref) < 1e-2f16) || abs((x - ref) / ref) < 1e-1f16;
}
@@ -1,6 +1,7 @@
#include "test_static.isph"
// rule: skip on arch=wasm32
// rule: skip on arch=wasm64
// rule: skip on arch=ppc64le
bool ok(float16 x, float16 ref) { return (abs(x - ref) < 1e-2f16) || abs((x - ref) / ref) < 1e-1f16; }
task void f_fu(uniform float RET[], uniform float aFOO[], uniform float b) {
varying float16 arg = aFOO[programIndex] + b;
+1
View File
@@ -1,4 +1,5 @@
#include "test_static.isph"
// rule: skip on arch=ppc64le
task void f_fu(uniform float RET[], uniform float aFOO[], uniform float b) {
float16 a = aFOO[programIndex];
RET[programIndex] = max(3 * a, 10.f16);
+1
View File
@@ -1,4 +1,5 @@
#include "test_static.isph"
// rule: skip on arch=ppc64le
task void f_fu(uniform float RET[], uniform float aFOO[], uniform float b) {
float16 a = aFOO[programIndex];
RET[programIndex] = max(-10 * (a - 3), .5f16);
+1
View File
@@ -1,4 +1,5 @@
#include "test_static.isph"
// rule: skip on arch=ppc64le
task void f_fu(uniform float RET[], uniform float aFOO[], uniform float b) {
float16 a = aFOO[programIndex];
RET[programIndex] = min(3 * a, 10.f16);
+1
View File
@@ -1,4 +1,5 @@
#include "test_static.isph"
// rule: skip on arch=ppc64le
task void f_fu(uniform float RET[], uniform float aFOO[], uniform float b) {
float16 a = aFOO[programIndex];
RET[programIndex] = min(-10 * (a - 3), .5f16);
@@ -1,4 +1,5 @@
#include "test_static.isph"
// rule: skip on arch=ppc64le
task void f_f(uniform float RET[], uniform float aFOO[]) {
uniform float16 a[programCount];
#pragma ignore warning(perf)
@@ -1,4 +1,5 @@
#include "test_static.isph"
// rule: skip on arch=ppc64le
task void f_f(uniform float RET[], uniform float aFOO[]) {
float a = aFOO[programIndex];
uniform float16 pack[programCount];
@@ -1,4 +1,5 @@
#include "test_static.isph"
// rule: skip on arch=ppc64le
task void f_f(uniform float RET[], uniform float aFOO[]) {
float a = aFOO[programIndex];
uniform float16 pack[programCount];
@@ -1,4 +1,5 @@
#include "test_static.isph"
// rule: skip on arch=ppc64le
static float float4(uniform float16 a, uniform float16 b, uniform float16 c, uniform float16 d) {
float ret = 0;
for (uniform int i = 0; i < programCount; i += 4) {
@@ -1,4 +1,5 @@
#include "test_static.isph"
// rule: skip on arch=ppc64le
static float float4(uniform float16 a, uniform float16 b, uniform float16 c, uniform float16 d) {
float ret = 0;
for (uniform int i = 0; i < programCount; i += 4) {
+1
View File
@@ -1,5 +1,6 @@
#include "test_static.isph"
// rule: skip on jit=true
// rule: skip on arch=ppc64le
task void print_uf(uniform float a) {
uniform float16 uniFloatVal = (float16)a + 4.75f16;
+1
View File
@@ -1,5 +1,6 @@
#include "test_static.isph"
// rule: skip on jit=true
// rule: skip on arch=ppc64le
task void print_f(uniform float aFOO[]) {
float16 a = aFOO[programIndex];
@@ -1,4 +1,5 @@
#include "test_static.isph"
// rule: skip on arch=ppc64le
task void f_fu(uniform float RET[], uniform float aFOO[], uniform float b) {
float16 v = aFOO[programIndex];
uniform float m;
@@ -1,4 +1,5 @@
#include "test_static.isph"
// rule: skip on arch=ppc64le
task void f_fu(uniform float RET[], uniform float aFOO[], uniform float b) {
float v = aFOO[programIndex];
uniform float m;
+1
View File
@@ -1,4 +1,5 @@
#include "test_static.isph"
// rule: skip on arch=ppc64le
task void f_fu(uniform float RET[], uniform float aFOO[], uniform float b) {
float16 v = aFOO[programIndex];
uniform float m;
+1
View File
@@ -1,3 +1,4 @@
// rule: skip on arch=ppc64le
#include "test_static.isph"
task void f_fu(uniform float RET[], uniform float aFOO[], uniform float b) {
float16 a = aFOO[programIndex];
+1
View File
@@ -1,3 +1,4 @@
// rule: skip on arch=ppc64le
#include "test_static.isph"
task void f_fu(uniform float RET[], uniform float aFOO[], uniform float b) {
#pragma ignore warning(perf)
+1
View File
@@ -1,4 +1,5 @@
#include "test_static.isph"
// rule: skip on arch=ppc64le
task void f_fu(uniform float RET[], uniform float aFOO[], uniform float b) {
float v = aFOO[programIndex];
uniform float m = 42;
+1
View File
@@ -1,4 +1,5 @@
#include "test_static.isph"
// rule: skip on arch=ppc64le
task void f_fu(uniform float RET[], uniform float aFOO[], uniform float b) {
float v = aFOO[programIndex];
uniform float m;
+1
View File
@@ -1,3 +1,4 @@
// rule: skip on arch=ppc64le
#include "test_static.isph"
task void f_fu(uniform float RET[], uniform float aFOO[], uniform float b) {
float16 a = aFOO[programIndex];
@@ -1,6 +1,7 @@
#include "test_static.isph"
// rule: skip on target=generic.*
// rule: run on OS=!windows
// rule: skip on arch=ppc64le
task void f_f(uniform float RET[], uniform float aFOO[]) {
float error = 0;
@@ -1,6 +1,7 @@
#include "test_static.isph"
// rule: skip on target=generic.*
// rule: run on OS=!windows
// rule: skip on arch=ppc64le
task void f_f(uniform float RET[], uniform float aFOO[]) {
uniform float error = 0;
+1
View File
@@ -1,4 +1,5 @@
#include "test_static.isph"
// rule: skip on arch=ppc64le
task void f_fu(uniform float RET[], uniform float aFOO[], uniform float b) {
float16 a = aFOO[programIndex];
uniform float16 a0 = RET[0];
+1
View File
@@ -1,3 +1,4 @@
// rule: skip on arch=ppc64le
#include "test_static.isph"
task void f_fu(uniform float RET[], uniform float aFOO[], uniform float b) {
RET[programIndex] = 0;
+1
View File
@@ -1,3 +1,4 @@
// rule: skip on arch=ppc64le
#include "test_static.isph"
task void f_fu(uniform float RET[], uniform float aFOO[], uniform float b) {
float16 a = aFOO[programIndex];
+1
View File
@@ -1,3 +1,4 @@
// rule: skip on arch=ppc64le
#include "test_static.isph"
task void f_fu(uniform float RET[], uniform float aFOO[], uniform float b) {
float16 aa = aFOO[programIndex];
@@ -1,4 +1,5 @@
#include "test_static.isph"
// rule: skip on arch=ppc64le
void var_store(uniform float16 a[], varying float x) {
streaming_store(a, x);
}
+1
View File
@@ -1,6 +1,7 @@
#include "test_static.isph"
// rule: skip on target=generic.*
// rule: run on OS=!windows
// rule: skip on arch=ppc64le
task void f_f(uniform float RET[], uniform float aFOO[]) {
float a = aFOO[programIndex];
RET[programIndex] = round(a+.49999);
+1
View File
@@ -1,6 +1,7 @@
#include "test_static.isph"
// rule: skip on target=generic.*
// rule: run on OS=!windows
// rule: skip on arch=ppc64le
task void f_f(uniform float RET[], uniform float aFOO[]) {
float a = aFOO[programIndex];
RET[programIndex] = round(a+.5);
@@ -1,4 +1,5 @@
#include "test_static.isph"
// rule: skip on arch=ppc64le
uniform bool ok(uniform float16 x, uniform float16 ref) { return (abs(x - ref) < 1e-7) || abs((x-ref)/ref) < 1e-6; }
task void f_fu(uniform float RET[], uniform float aFOO[], uniform float b) {
for (uniform int i = 0; i != programCount; ++i) {
@@ -1,4 +1,5 @@
#include "test_static.isph"
// rule: skip on arch=ppc64le
uniform bool ok(uniform float16 x, uniform float16 ref) { return (abs(x - ref) < 1e-6) || abs((x-ref)/ref) < 1e-5; }
task void f_fu(uniform float RET[], uniform float aFOO[], uniform float b) {
for (uniform int i = 0; i != programCount; ++i) {
@@ -1,4 +1,5 @@
#include "test_static.isph"
// rule: skip on arch=ppc64le
bool ok(float16 x, float16 ref) { return (abs(x - ref) < 1e-6) || abs((x-ref)/ref) < 1e-5; }
task void f_fu(uniform float RET[], uniform float aFOO[], uniform float b) {
varying float16 arg = aFOO[programIndex] / (programCount + 2.0f16);
@@ -1,4 +1,5 @@
#include "test_static.isph"
// rule: skip on arch=ppc64le
uniform bool ok(uniform float16 x, uniform float16 ref) { return (abs(x - ref) < 1e-7) || abs((x-ref)/ref) < 1e-6; }
task void f_fu(uniform float RET[], uniform float aFOO[], uniform float b) {
for (uniform int i = 0; i != programCount; ++i) {
@@ -1,4 +1,5 @@
#include "test_static.isph"
// rule: skip on arch=ppc64le
bool ok(float16 x, float16 ref) { return (abs(x - ref) < 1e-7) || abs((x-ref)/ref) < 1e-6; }
task void f_fu(uniform float RET[], uniform float aFOO[], uniform float b) {
varying float16 arg = aFOO[programIndex];
@@ -1,4 +1,5 @@
#include "test_static.isph"
// rule: skip on arch=ppc64le
uniform bool ok(uniform float16 x, uniform float16 ref) { return (abs(x - ref) < 1e-7) || abs((x-ref)/ref) < 1e-6; }
task void f_fu(uniform float RET[], uniform float aFOO[], uniform float b) {
for (uniform int i = 0; i != programCount; ++i) {
@@ -1,4 +1,5 @@
#include "test_static.isph"
// rule: skip on arch=ppc64le
bool ok(float16 x, float16 ref) { return (abs(x - ref) < 1e-5) || abs((x-ref)/ref) < 1e-4; }
task void f_fu(uniform float RET[], uniform float aFOO[], uniform float b) {
varying float16 arg = aFOO[programIndex];
@@ -1,4 +1,5 @@
#include "test_static.isph"
// rule: skip on arch=ppc64le
uniform bool ok(uniform float16 x, uniform float16 ref) { return (abs(x - ref) < 1e-5) || abs((x-ref)/ref) < 1e-4; }
task void f_fu(uniform float RET[], uniform float aFOO[], uniform float b) {
for (uniform int i = 0; i != programCount; ++i) {
@@ -1,4 +1,5 @@
#include "test_static.isph"
// rule: skip on arch=ppc64le
bool ok(float16 x, float16 ref) { return (abs(x - ref) < 1e-5) || abs((x-ref)/ref) < 1e-4; }
task void f_fu(uniform float RET[], uniform float aFOO[], uniform float b) {
varying float16 arg = aFOO[programIndex] + b;
@@ -1,4 +1,5 @@
#include "test_static.isph"
// rule: skip on arch=ppc64le
uniform bool ok(uniform float16 x, uniform float16 ref) { return (abs(x - ref) < 1e-5) || abs((x-ref)/ref) < 1e-4; }
task void f_fu(uniform float RET[], uniform float aFOO[], uniform float b) {
for (uniform int i = 0; i != programCount; ++i) {
@@ -1,4 +1,5 @@
#include "test_static.isph"
// rule: skip on arch=ppc64le
bool ok(float16 x, float16 ref) { return (abs(x - ref) < 1e-5) || abs((x-ref)/ref) < 1e-4; }
task void f_fu(uniform float RET[], uniform float aFOO[], uniform float b) {
varying float16 arg = aFOO[programIndex] + b;
@@ -4,6 +4,7 @@
// rule: run on OS=linux
// rule: skip on arch=wasm32
// rule: skip on arch=wasm64
// rule: skip on arch=ppc64le
uniform bool ok(uniform float16 x, uniform float16 ref) { return (abs(x - ref) < 1e-4) || abs((x-ref)/ref) < 1e-3; }
task void f_fu(uniform float RET[], uniform float aFOO[], uniform float b) {
for (uniform int i = 0; i != programCount; ++i) {
@@ -2,6 +2,7 @@
// sincos() function is available only on Linux.
// rule: skip on OS=*
// rule: run on OS=linux
// rule: skip on arch=ppc64le
bool ok(float16 x, float16 ref) { return (abs(x - ref) < 1e-4) || abs((x-ref)/ref) < 1e-3; }
task void f_fu(uniform float RET[], uniform float aFOO[], uniform float b) {
varying float16 arg = aFOO[programIndex];
@@ -1,4 +1,5 @@
#include "test_static.isph"
// rule: skip on arch=ppc64le
uniform bool ok(uniform float16 x, uniform float16 ref) { return (abs(x - ref) < 1e-4) || abs((x-ref)/ref) < 1e-3; }
task void f_fu(uniform float RET[], uniform float aFOO[], uniform float b) {
@@ -1,4 +1,5 @@
#include "test_static.isph"
// rule: skip on arch=ppc64le
bool ok(float16 x, float16 ref) { return (abs(x - ref) < 1e-4) || abs((x-ref)/ref) < 1e-3; }
task void f_fu(uniform float RET[], uniform float aFOO[], uniform float b) {
@@ -1,4 +1,5 @@
#include "test_static.isph"
// rule: skip on arch=ppc64le
task void f_f(uniform float RET[], uniform float aFOO[]) {
uniform float error = 0;
RET[programIndex] = 0;
@@ -1,6 +1,7 @@
#include "test_static.isph"
// rule: skip on arch=wasm32
// rule: skip on arch=wasm64
// rule: skip on arch=ppc64le
task void f_f(uniform float RET[], uniform float aFOO[]) {
float error = 0;
RET[programIndex] = 0;
@@ -1,4 +1,5 @@
#include "test_static.isph"
// rule: skip on arch=ppc64le
task void f_f(uniform float RET[], uniform float aFOO[]) {
#pragma ignore warning(perf)
uniform float16 x = aFOO[programCount / 2];
@@ -1,4 +1,5 @@
#include "test_static.isph"
// rule: skip on arch=ppc64le
task void f_f(uniform float RET[], uniform float aFOO[]) {
uniform float16 x = aFOO[programCount/2];
uniform float16 d, invsqrt = rsqrt(x);
@@ -1,4 +1,5 @@
#include "test_static.isph"
// rule: skip on arch=ppc64le
task void f_f(uniform float RET[], uniform float aFOO[]) {
uniform float16 f = aFOO[programCount]/4;
uniform float16 calc = sqrt(f) * sqrt(f) - aFOO[programCount]/4;
@@ -1,4 +1,5 @@
#include "test_static.isph"
// rule: skip on arch=ppc64le
task void f_f(uniform float RET[], uniform float aFOO[]) {
#pragma ignore warning(perf)
varying float16 x = aFOO[programIndex];
@@ -1,4 +1,5 @@
#include "test_static.isph"
// rule: skip on arch=ppc64le
task void f_f(uniform float RET[], uniform float aFOO[]) {
varying float16 x = aFOO[programIndex/2];
varying float16 d, invsqrt = rsqrt(x);
+4
View File
@@ -6,6 +6,10 @@
// RUN: %t.c.bin | FileCheck %s
// REQUIRES: !MACOS_HOST
// ISPC assertion failure in lAllDivBaseEqual (llvmutil.cpp) for generic
// targets: the integer divide optimization passes a non-power-of-2 baseValue.
// TODO: Fix this ISPC bug for generic targets.
// XFAIL: PPC64LE_HOST
// CHECK-NOT: Floating point exception
// CHECK: Correct result
+4
View File
@@ -1,6 +1,10 @@
// RUN: %{ispc} %s --target=host --opt=fast-math --nostdlib --nowrap 2>&1 | FileCheck %s -check-prefix=CHECK_WARN
// RUN: %{ispc} %s --target=host --opt=fast-math -O0 --emit-llvm-text -o -| FileCheck %s -check-prefix=CHECK_NOFDIV
// Generic target stdlib's rcp implementation uses 1.0/x (fdiv) rather than
// a hardware rcp instruction, so the CHECK_NOFDIV check fails on ppc64le.
// XFAIL: PPC64LE_HOST
// CHECK_NOFDIV-NOT: fdiv
@@ -0,0 +1,33 @@
// Test generic targets for ppc64le architecture
// Verifies that generic targets produce correct LLVM IR vector types for ppc64le.
// RUN: %{ispc} --target=generic-i1x4 --arch=ppc64le --nostdlib --nowrap %s --emit-llvm-text -o - 2>&1 | FileCheck %s --check-prefix=CHECK-I1X4
// RUN: %{ispc} --target=generic-i1x8 --arch=ppc64le --nostdlib --nowrap %s --emit-llvm-text -o - 2>&1 | FileCheck %s --check-prefix=CHECK-I1X8
// RUN: %{ispc} --target=generic-i1x16 --arch=ppc64le --nostdlib --nowrap %s --emit-llvm-text -o - 2>&1 | FileCheck %s --check-prefix=CHECK-I1X16
// RUN: %{ispc} --target=generic-i1x32 --arch=ppc64le --nostdlib --nowrap %s --emit-llvm-text -o - 2>&1 | FileCheck %s --check-prefix=CHECK-I1X32
// RUN: %{ispc} --target=generic-i1x64 --arch=ppc64le --nostdlib --nowrap %s --emit-llvm-text -o - 2>&1 | FileCheck %s --check-prefix=CHECK-I1X64
// RUN: %{ispc} --target=generic-i8x16 --arch=ppc64le --nostdlib --nowrap %s --emit-llvm-text -o - 2>&1 | FileCheck %s --check-prefix=CHECK-I8X16
// RUN: %{ispc} --target=generic-i8x32 --arch=ppc64le --nostdlib --nowrap %s --emit-llvm-text -o - 2>&1 | FileCheck %s --check-prefix=CHECK-I8X32
// RUN: %{ispc} --target=generic-i16x8 --arch=ppc64le --nostdlib --nowrap %s --emit-llvm-text -o - 2>&1 | FileCheck %s --check-prefix=CHECK-I16X8
// RUN: %{ispc} --target=generic-i16x16 --arch=ppc64le --nostdlib --nowrap %s --emit-llvm-text -o - 2>&1 | FileCheck %s --check-prefix=CHECK-I16X16
// RUN: %{ispc} --target=generic-i32x4 --arch=ppc64le --nostdlib --nowrap %s --emit-llvm-text -o - 2>&1 | FileCheck %s --check-prefix=CHECK-I32X4
// RUN: %{ispc} --target=generic-i32x8 --arch=ppc64le --nostdlib --nowrap %s --emit-llvm-text -o - 2>&1 | FileCheck %s --check-prefix=CHECK-I32X8
// RUN: %{ispc} --target=generic-i32x16 --arch=ppc64le --nostdlib --nowrap %s --emit-llvm-text -o - 2>&1 | FileCheck %s --check-prefix=CHECK-I32X16
// RUN: %{ispc} --target=generic-i64x4 --arch=ppc64le --nostdlib --nowrap %s --emit-llvm-text -o - 2>&1 | FileCheck %s --check-prefix=CHECK-I64X4
// REQUIRES: PPC64_ENABLED && LINUX_ENABLED
// CHECK-I1X4: define <4 x i32> @bar___vyi(<4 x i32> returned %x, <4 x i1> %__mask)
// CHECK-I1X8: define <8 x i32> @bar___vyi(<8 x i32> returned %x, <8 x i1> %__mask)
// CHECK-I1X16: define <16 x i32> @bar___vyi(<16 x i32> returned %x, <16 x i1> %__mask)
// CHECK-I1X32: define <32 x i32> @bar___vyi(<32 x i32> returned %x, <32 x i1> %__mask)
// CHECK-I1X64: define <64 x i32> @bar___vyi(<64 x i32> returned %x, <64 x i1> %__mask)
// CHECK-I8X16: define <16 x i32> @bar___vyi(<16 x i32> returned %x, <16 x i8> %__mask)
// CHECK-I8X32: define <32 x i32> @bar___vyi(<32 x i32> returned %x, <32 x i8> %__mask)
// CHECK-I16X8: define <8 x i32> @bar___vyi(<8 x i32> returned %x, <8 x i16> %__mask)
// CHECK-I16X16: define <16 x i32> @bar___vyi(<16 x i32> returned %x, <16 x i16> %__mask)
// CHECK-I32X4: define <4 x i32> @bar___vyi(<4 x i32> returned %x, <4 x i32> %__mask)
// CHECK-I32X8: define <8 x i32> @bar___vyi(<8 x i32> returned %x, <8 x i32> %__mask)
// CHECK-I32X16: define <16 x i32> @bar___vyi(<16 x i32> returned %x, <16 x i32> %__mask)
// CHECK-I64X4: define <4 x i32> @bar___vyi(<4 x i32> returned %x, <4 x i64> %__mask)
int bar(int x) { return x; }
+13
View File
@@ -136,6 +136,16 @@ elif riscv_enabled == "OFF":
else:
sys.exit("Cannot parse riscv_enabled: " + riscv_enabled)
# PowerPC64 backend
ppc64_enabled = lit_config.params.get('ppc64_enabled')
if ppc64_enabled == "ON":
print("PPC64_ENABLED: YES")
config.available_features.add("PPC64_ENABLED")
elif ppc64_enabled == "OFF":
print("PPC64_ENABLED: NO")
else:
sys.exit("Cannot parse ppc64_enabled: " + ppc64_enabled)
# WebAssembly backend
wasm_enabled = lit_config.params.get('wasm_enabled')
if wasm_enabled == "ON":
@@ -226,6 +236,9 @@ elif host_arch == "aarch64":
elif host_arch == "riscv64":
print("HOST ARCH: RISCV64")
config.available_features.add("RISCV64_HOST")
elif host_arch == "ppc64le":
print("HOST ARCH: PPC64LE")
config.available_features.add("PPC64LE_HOST")
else:
print(f"HOST ARCH: {host_arch} (unknown)")
config.available_features.add("UNKNOWN_HOST_ARCH")
+3
View File
@@ -4,6 +4,9 @@
// RUN: %t.c.bin | FileCheck %s
// REQUIRES: !MACOS_HOST
// ABI mismatch between ISPC and clang on ppc64le for int8/int16 return types:
// int8_min and int16_min return incorrect values when linked with clang.
// XFAIL: PPC64LE_HOST
// CHECK: int8_min: 1
// CHECK: int8_max: 1
+23
View File
@@ -0,0 +1,23 @@
// Test that PowerPC VSX vector instructions are generated for ppc64le targets.
// RUN: %{ispc} %s --target=generic-i32x4 --arch=ppc64le --target-os=linux --nowrap --emit-asm -o - | FileCheck %s
// REQUIRES: PPC64_ENABLED && LINUX_ENABLED
// CHECK-LABEL: vadd___un_3C_unf_3E_un_3C_unf_3E_un_3C_unf_3E_uni:
// CHECK: xvaddsp
void vadd(uniform float a[], uniform float b[], uniform float result[], uniform int count) {
foreach (i = 0 ... count) {
result[i] = a[i] + b[i];
}
}
// CHECK-LABEL: vmul___un_3C_unf_3E_un_3C_unf_3E_un_3C_unf_3E_uni:
// CHECK: xvmulsp
void vmul(uniform float a[], uniform float b[], uniform float result[], uniform int count) {
foreach (i = 0 ... count) {
result[i] = a[i] * b[i];
}
}
@@ -3,6 +3,10 @@
// RUN: %{ispc} --target=host -o %t.o %s 2>&1
// LLVM 20 PowerPC backend can't select froundeven for vector types
// (Cannot select: v4f32 = froundeven). Fixed in LLVM 21 by PR #150597.
// XFAIL: PPC64LE_HOST && !LLVM_21_0+
#include <short_vec.isph>
#define VARYING(NAME, TYPE, N) \
@@ -3,6 +3,10 @@
// RUN: %{ispc} --target=host -o %t.o %s 2>&1
// LLVM 20 PowerPC backend crashes on vector atan2/pow/fmod with
// "Do not know how to promote this operator's result!". Fixed in LLVM 21.
// XFAIL: PPC64LE_HOST && !LLVM_21_0+
#include <short_vec.isph>
#define VARYING(NAME, TYPE, N) \
+3 -1
View File
@@ -1,5 +1,5 @@
/*
Copyright (c) 2013-2025, Intel Corporation
Copyright (c) 2013-2026, Intel Corporation
SPDX-License-Identifier: BSD-3-Clause
*/
@@ -69,6 +69,8 @@ static const char *lGetSystemISA() {
return isa;
#elif defined(__riscv)
return "RISC-V";
#elif defined(__powerpc64__) && (__BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__)
return "PPC64LE";
#else
#error "Unsupported host CPU architecture."
#endif
+9
View File
@@ -117,6 +117,15 @@ int main(int argc, char **argv) {
LLVMInitializeRISCVTargetMC();
#endif
#ifdef ISPC_PPC64_ENABLED
LLVMInitializePowerPCTargetInfo();
LLVMInitializePowerPCTarget();
LLVMInitializePowerPCAsmPrinter();
LLVMInitializePowerPCAsmParser();
LLVMInitializePowerPCDisassembler();
LLVMInitializePowerPCTargetMC();
#endif
#ifdef ISPC_WASM_ENABLED
LLVMInitializeWebAssemblyAsmParser();
LLVMInitializeWebAssemblyAsmPrinter();