LLVM commit d19e954b83cb made -use-constant-fp-for-fixed-length-splat
the default, causing LLVM to represent fixed-length FP vector splats as
ConstantFP with vector type instead of ConstantDataVector. This caused
ISPC to crash on an assertion in lVectorValuesAllEqual.
Changes:
- Add ConstantFP with vector type handling to lVectorValuesAllEqual
- Replace assertion with conservative return false for unhandled constants
- Add ConstantFP with vector type handling to lExtractFirstVectorElement
- Add regression test for scatter with uniform float values
Generated with [Claude Code](https://claude.com/claude-code)
Co-authored-by: aneshlya <aneshlya@users.noreply.github.com>
- acos now correctly calls the standard library in double precision
- implement faster versions which are also much more accurate close to 1 (no catastrophic cancellation anymore)
- improve the acos tests so to check more use-case and reduce the error bound
The new default math-lib log implementation now correctly support special values (as opposed to the previous one):
- Subnormal numbers
- Infinities
- NaNs
This new default implementation also reduces the error from about ~3000 ULP (close to 1, due to a catastrophic cancellation) to <4 ULP.
The fast-math-lib implementation is now significantly faster (although less precise: <30 ULP vs <2 ULP).
LLVM trunk commit removed the two-argument getInlineParams(optLevel, SizeOptLevel)
overload in favor of getInlineParamsFromOptLevel(optLevel). Size optimization
is now handled via function attributes (optsize/minsize) instead of a
pipeline-level SizeOptLevel parameter.
This commit adds version guards to use:
- getInlineParamsFromOptLevel(optLevel) for LLVM 23+
- getInlineParams(optLevel, SizeOptLevel) for LLVM ≤22
Fixes#3790
Co-authored-by: Aleksei Nurmukhametov <nurmukhametov@users.noreply.github.com>
When a function has dead varying code (e.g. `uint8 y = x[0]` where y is
unused), ISPC generates a masked load in the `some_on` path. After
optimization, the unused masked load gets reduced by InstCombine to a
select with the passthrough value:
%res = select <8 x i1> %mask, <8 x i8> %x, <8 x i8> undef
This select flows into a phi node in the common return block:
%rv = phi <8 x i8> [ %res, %loop ], [ %x, %entry ], [ %x, %some_on ]
%ret = add <8 x i8> %rv, splat (i8 1)
ret <8 x i8> %ret
LLVM cannot simplify `select(mask, x, undef)` to `x` because undef
semantics require each use to independently pick an arbitrary value,
so folding would change the possible outcomes. With the phi having
non-identical incoming values, SimplifyCFG cannot merge the blocks,
leaving the mask-checking control flow (vmovmskps/vtestps/cmp/jmp)
in the final assembly as dead weight.
Changing the passthrough from `undef` to `poison` fixes this because
`select(mask, x, poison)` legally simplifies to `x` as poison is
strictly more permissive. This makes all phi incoming values identical
(%x), allowing SimplifyCFG to collapse the three blocks into one and
eliminate the redundant branches entirely.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* Implement the function erf (WIP)
* Significantly improve the precision of the AS approx
* Fix NaNs issues, improve the precision of all implementations, and provide a real/tested error bound
* Significantly more precise fast-math-lib implementation
* Clang format
* Fix tests (exp wrongly called instead of erf)
* Fix the last year in copyright headers
* Force erf(x) to be exactly 1.0 for abs(x)>=4 in the default implementation
* Fix also the double-precision test (erf vs exp)
LLVM 23.0 deprecated llvm::BranchInst and split it into UncondBrInst
and CondBrInst. This commit updates all 4 call sites with version
guards to maintain backward compatibility with LLVM 18-22.
Changes:
- src/ctx.cpp: Updated 3 call sites (lines 235, 3493, 3509)
- Unconditional branches now use UncondBrInst::Create
- Conditional branch uses CondBrInst::Create with reordered arguments
- src/module.cpp: Updated 1 call site (line 2068)
- Conditional branch uses CondBrInst::Create with reordered arguments
- Updated copyright year to 2026 in src/module.cpp
All changes are guarded with #if ISPC_LLVM_VERSION >= ISPC_LLVM_23_0
to preserve compatibility with earlier LLVM versions.
Co-authored-by: aneshlya <aneshlya@users.noreply.github.com>
* Make fast-math optimizations more aggressive
* Support the legacy fast-math mode and add 2 new ones (safe + unsafe)
* Better naming for fast-math modes (and remove a TODO)
* Fix the formatting and remove an unused old define
* Fix fast-math tests
* Re-enable reciprocal in the balanced mode and fix/improve tests
* Add a description of the fast-math modes in the help
* Fix tests (limitation to x86 arch + stable arch for all tests) and summary what they do
* Fix tests: regexp fix + split due to MacOS not supporting avx512spr required for native float16 support
* Disable FastMathPass in legacy mode
* Adapt notes about PPC64LE and removes the (now) unnecessary XFAIL
* Add some doc about fast-math modes and the rcp function + update the changelogs
* Clarification of the doc about fast-math modes
* Apply fast-math flags to more instructions (e.g. calls, select, phi, unary ops, etc.)
New vsx-target.ispc tests all 6 targets plus the "vsx" alias by
checking vector width in LLVM IR output. Also add a vsx-i32x4 RUN
line to the existing ppc64le-vector-asm test.
Minimal stubs that only define WIDTH, MASK, and ISA macros — just
enough for the builtin system to register them. Actual intrinsic
implementations can be added later, following the same approach used
for NEON (commit 8af7dcf3).
Add PPC64_TARGETS list in CMakeLists.txt, define stdlib families for
the 6 VSX targets, handle vsx arch detection in bitcode2cpp.py and
CommonStdlibBuiltins.cmake.
Hook up the new VSX targets in the compiler core: add VSX to the ISA
enum, define target constructor cases with vector width/alignment/mask
properties matching their generic parents, and add the necessary CPU
mapping, arch detection, and feature string logic.
Add 6 new ISPCTarget enum values for PowerPC VSX targets: vsx_i8x16,
vsx_i8x32, vsx_i16x8, vsx_i16x16, vsx_i32x4, and vsx_i32x8. These
mirror NEON's target set with explicit data type naming.
Includes ParseISPCTarget entries (with "vsx" alias mapping to
vsx_i32x4), ISPCTargetToString cases, static_assert chain updates,
and the ISPCTargetIsVSX() helper function.
FILE_CHECK_EXECUTABLE can be set at CMake configure time (e.g.,
-DFILE_CHECK_EXECUTABLE=FileCheck-20) to use a custom FileCheck binary.
Previously this value wasn’t passed to lit, so tests always invoked the default
FileCheck and failed if it wasn’t on the PATH.
Add step 6 to the "Implementing a feature or fixing a bug" workflow in
CLAUDE.md instructing to check git history of changed files after the
fix is implemented, to verify no previously fixed bugs were
re-introduced. Documents git log --oneline, git log -L and git show
as useful commands for this purpose.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* 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
The commit f80c6e0c changed I1VecToBoolVec to produce [N x <W x iMASK>]
for bool short-vector comparison results, intending to make varying bool<N>
consistent with scalar varying bool (which uses BoolVectorType = iMASK
internally). However it did not update lGetVectorLLVMType, which still
returned [N x <W x i8>] (storage type) for VectorType::LLVMType() on
varying bool<N>. This mismatch caused "Call parameter type does not match
function signature" when a comparison result was passed directly to a
function expecting bool<N>.
Fix: complete the original intent by removing the !base->IsUniformType()
exception in lGetVectorLLVMType so that LLVMType() for varying bool<N>
returns [N x <W x iMASK>] (consistent with I1VecToBoolVec), while
LLVMStorageType() continues to return [N x <W x i8>]. Update TypeCastExpr
to match: build the output array with LLVMType and use SwitchBoolToMaskType
for bool elements in both the vector-to-vector and scalar-to-vector paths.
This design is now fully symmetric: both scalar varying bool and varying
bool<N> use the target-specific mask type internally (e.g. i32 on AVX2,
i1 on AVX-512) and convert to i8 only at store/load/ABI boundaries.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
LLVM trunk changed instruction selection for FMA operations in unrolled
loops, now consistently generating vfmadd231ps instead of mixing
vfmadd132ps and vfmadd231ps. All three FMA variants (132/213/231) are
semantically equivalent, differing only in register operand order.
Updated CHECK patterns to use vfmadd{{[0-9]+}}ps regex to match any
FMA variant, making the test robust to LLVM's internal codegen decisions
while still verifying the loop unrolling behavior.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Co-authored-by: aneshlya <aneshlya@users.noreply.github.com>
ispc-opt runs optimization passes on LLVM IR and does not require the
bitcode libraries provided by the builtin target. Previously, it was
linked against builtin primarily to satisfy a target validation check in
the Target constructor that relies on the target registry.