Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support building against llvm15 #1035

Merged
merged 11 commits into from
Mar 30, 2024
10 changes: 10 additions & 0 deletions azure-pipelines.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,11 @@ jobs:
PYTHON: '3.12'
CONDA_ENV: cienv

llvm15:
PYTHON: '3.12'
CONDA_ENV: cienv
LLVM: '15'

- template: buildscripts/azure/azure-linux-macos.yml
parameters:
name: Linux
Expand Down Expand Up @@ -67,6 +72,11 @@ jobs:
CONDA_ENV: cienv
BUILD_DOCS: 'yes'

llvm15:
PYTHON: '3.12'
CONDA_ENV: cienv
LLVM: '15'

- template: buildscripts/azure/azure-windows.yml
parameters:
name: Windows
Expand Down
10 changes: 5 additions & 5 deletions buildscripts/azure/azure-windows.yml
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,10 @@ jobs:
PYTHON: '3.12'
CONDA_ENV: cienv

llvm15:
PYTHON: '3.12'
CONDA_ENV: cienv
LLVM: '15'

steps:

Expand All @@ -33,11 +37,7 @@ jobs:

- script: |
call C:\Miniconda3\Scripts\activate.bat
call conda list
call conda remove --all -q -y -n %CONDA_ENV%
call conda create -n %CONDA_ENV% -q -y python=%PYTHON% cmake
call activate %CONDA_ENV%
call conda install -y -q -c numba/label/dev llvmdev="14.*" libxml2
call buildscripts\\incremental\\setup_conda_environment.cmd
displayName: 'Before Install'

- script: |
Expand Down
19 changes: 19 additions & 0 deletions buildscripts/incremental/build.cmd
Original file line number Diff line number Diff line change
@@ -1,4 +1,23 @@

call activate %CONDA_ENV%

@rem LLVM derives the location of diaguids.lib from the build-time environment.
@rem Conda-forge packaging works around this by substituting the build-time
@rem location of Visual Studio with $ENV{VSINSTALLDIR}. In order to ensure that
@rem this environment variable is set appropriately, we activate the Visual
@rem Studio Developer Command Prompt prior to running setup.py
@rem
@rem This workaround is required whilst using LLVM from conda-forge; it may also
@rem be necessary to consider a workaround for our own llvmdev packages.
@rem
@rem For more info, see:
@rem
@rem - https://github.com/conda-forge/llvmdev-feedstock/issues/175
@rem - https://github.com/conda-forge/llvmdev-feedstock/pull/223
@rem - https://github.com/MicrosoftDocs/visualstudio-docs/issues/7774
if "%LLVM%"=="15" (
call "C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\Common7\Tools\VsDevCmd.bat"
if %errorlevel% neq 0 exit /b %errorlevel%
)

python setup.py build
22 changes: 11 additions & 11 deletions buildscripts/incremental/setup_conda_environment.cmd
Original file line number Diff line number Diff line change
@@ -1,24 +1,24 @@
@rem The cmd /C hack circumvents a regression where conda installs a conda.bat
@rem script in non-root environments.
set CONDA_INSTALL=cmd /C conda install -q -y
set PIP_INSTALL=pip install -q

@echo on

@rem Deactivate any environment
call deactivate
@rem Display root environment (for debugging)
conda list
call conda list

@rem Clean up any left-over from a previous build
conda remove --all -q -y -n %CONDA_ENV%
call conda remove --all -q -y -n %CONDA_ENV%

@rem Create and populate environment
conda create -n %CONDA_ENV% -q -y python=%PYTHON% cmake
call conda create -n %CONDA_ENV% -q -y python=%PYTHON% cmake
if %errorlevel% neq 0 exit /b %errorlevel%

call activate %CONDA_ENV%
if %errorlevel% neq 0 exit /b %errorlevel%

@rem Install llvmdev
%CONDA_INSTALL% -c numba/label/dev llvmdev="14.*"
if "%LLVM%"=="15" (
set LLVMDEV_CHANNEL="conda-forge"
) else (
set LLVMDEV_CHANNEL="numba/label/dev"
)

call conda install -y -q -c %LLVMDEV_CHANNEL% llvmdev="%LLVM%" libxml2
if %errorlevel% neq 0 exit /b %errorlevel%
6 changes: 5 additions & 1 deletion buildscripts/incremental/setup_conda_environment.sh
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,11 @@ source activate $CONDA_ENV
set -v

# Install llvmdev (separate channel, for now)
$CONDA_INSTALL -c numba/label/dev llvmdev="14.*"
if [ "$LLVM" == "15" ]; then
$CONDA_INSTALL -c conda-forge llvmdev="15"
else
$CONDA_INSTALL -c numba/label/dev llvmdev="14.*"
fi

# Install the compiler toolchain, for osx, bootstrapping needed
# which happens in build.sh
Expand Down
4 changes: 4 additions & 0 deletions ffi/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,10 @@ if(NOT MSVC)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fno-rtti -g")
endif()

# Work around llvm/llvm-project#83802 - LLVM's Findzstd.cmake uses variables
# that require including `GNUInstallDirs`, but it does not include it itself.
include(GNUInstallDirs)

find_package(LLVM REQUIRED CONFIG)

message(STATUS "Found LLVM ${LLVM_PACKAGE_VERSION}")
Expand Down
21 changes: 14 additions & 7 deletions ffi/build.py
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,13 @@ def run_llvm_config(llvm_config, args):
return out


def show_warning(message):
header = ' * '.join(("WARNING",) * 8)
blk = '=' * 80
warning = f'{blk}\n{header}\n{blk}'
print(f"{warning}\n{message}\n{warning}")


def find_windows_generator():
"""
Find a suitable cmake "generator" under Windows.
Expand Down Expand Up @@ -156,16 +163,16 @@ def main_posix(kind, library_ext):
"overridden.\nThis is unsupported behaviour, llvmlite may not "
"work as intended.\nRequested LLVM version: {}".format(
out.strip()))
warn = ' * '.join(("WARNING",) * 8)
blk = '=' * 80
warning = '{}\n{}\n{}'.format(blk, warn, blk)
print(warning)
print(msg)
print(warning + '\n')
show_warning(msg)
else:
(version, _) = out.split('.', 1)
version = int(version)
if version != 14:
if version == 15:
msg = ("Building with LLVM 15; note that LLVM 15 support is "
"presently experimental")
show_warning(msg)
elif version != 14:

msg = ("Building llvmlite requires LLVM 14, got "
"{!r}. Be sure to set LLVM_CONFIG to the right executable "
"path.\nRead the documentation at "
Expand Down
16 changes: 14 additions & 2 deletions ffi/core.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,22 @@ API_EXPORT(void)
LLVMPY_DisposeString(const char *msg) { free(const_cast<char *>(msg)); }

API_EXPORT(LLVMContextRef)
LLVMPY_GetGlobalContext() { return LLVMGetGlobalContext(); }
LLVMPY_GetGlobalContext() {
auto context = LLVMGetGlobalContext();
#if LLVM_VERSION_MAJOR > 14
LLVMContextSetOpaquePointers(context, false);
#endif
return context;
}

API_EXPORT(LLVMContextRef)
LLVMPY_ContextCreate() { return LLVMContextCreate(); }
LLVMPY_ContextCreate() {
LLVMContextRef context = LLVMContextCreate();
#if LLVM_VERSION_MAJOR > 14
LLVMContextSetOpaquePointers(context, false);
#endif
return context;
}

API_EXPORT(void)
LLVMPY_ContextDispose(LLVMContextRef context) {
Expand Down
5 changes: 5 additions & 0 deletions ffi/core.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,11 @@
#define LLVMPY_CORE_H_

#include "llvm-c/Core.h"

// Needed for macros that control version-specific behaviour - included here so
// that they are available in all ffi translation units
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In particular, this defines the LLVM_VERSION_MAJOR macro referenced in various places in this PR.

#include "llvm/Config/llvm-config.h"

#include <cstdlib>
#include <cstring>

Expand Down
9 changes: 9 additions & 0 deletions ffi/orcjit.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -158,7 +158,12 @@ LLVMPY_LLJITLookup(std::shared_ptr<LLJIT> *lljit, const char *dylib_name,
return nullptr;
}

#if LLVM_VERSION_MAJOR <= 14
*addr = sym->getAddress();
#else
*addr = sym->getValue();
#endif

return new JITDylibTracker(*lljit, *dylib,
std::move(dylib->createResourceTracker()));
}
Expand Down Expand Up @@ -334,7 +339,11 @@ LLVMPY_LLJIT_Link(std::shared_ptr<LLJIT> *lljit, const char *libraryName,
LLVMDisposeErrorMessage(message);
return nullptr;
}
#if LLVM_VERSION_MAJOR <= 14
exports[export_idx].address = lookup->getAddress();
#else
exports[export_idx].address = lookup->getValue();
#endif
}
return new JITDylibTracker(*lljit, *dylib,
std::move(dylib->getDefaultResourceTracker()));
Expand Down
14 changes: 14 additions & 0 deletions ffi/passmanagers.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -161,8 +161,13 @@ LLVMPY_AddCallGraphDOTPrinterPass(LLVMPassManagerRef PM) {

API_EXPORT(void)
LLVMPY_AddDotDomPrinterPass(LLVMPassManagerRef PM, bool showBody) {
#if LLVM_VERSION_MAJOR <= 14

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggest being consistent with the #ifs, either all "<= 14" or all "< 15"

unwrap(PM)->add(showBody ? llvm::createDomPrinterPass()
: llvm::createDomOnlyPrinterPass());
#else
unwrap(PM)->add(showBody ? llvm::createDomPrinterWrapperPassPass()
: llvm::createDomOnlyPrinterWrapperPassPass());
#endif
}

API_EXPORT(void)
Expand All @@ -172,8 +177,13 @@ LLVMPY_AddGlobalsModRefAAPass(LLVMPassManagerRef PM) {

API_EXPORT(void)
LLVMPY_AddDotPostDomPrinterPass(LLVMPassManagerRef PM, bool showBody) {
#if LLVM_VERSION_MAJOR <= 14
unwrap(PM)->add(showBody ? llvm::createPostDomPrinterPass()
: llvm::createPostDomOnlyPrinterPass());
#else
unwrap(PM)->add(showBody ? llvm::createPostDomPrinterWrapperPassPass()
: llvm::createPostDomOnlyPrinterWrapperPassPass());
#endif
}

API_EXPORT(void)
Expand Down Expand Up @@ -244,10 +254,12 @@ LLVMPY_AddAlwaysInlinerPass(LLVMPassManagerRef PM, bool insertLifetime) {
unwrap(PM)->add(llvm::createAlwaysInlinerLegacyPass(insertLifetime));
}

#if LLVM_VERSION_MAJOR < 15
API_EXPORT(void)
LLVMPY_AddArgPromotionPass(LLVMPassManagerRef PM, unsigned int maxElements) {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ditto with ArgumentPromotionPass in NPM as below

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Did you mean legacy version of this pass is available as well? I couldn't find it.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry I meant the new pass version, I wrote both of these comments together then saw the legacy pass still existed.

On that note, the NPM setup slots in differently (using pipeline tuning options) so we can’t replace these in-situ. No needed for this change though.

unwrap(PM)->add(llvm::createArgumentPromotionPass(maxElements));
}
#endif

API_EXPORT(void)
LLVMPY_AddBreakCriticalEdgesPass(LLVMPassManagerRef PM) {
Expand Down Expand Up @@ -333,12 +345,14 @@ LLVMPY_AddLoopUnrollAndJamPass(LLVMPassManagerRef PM) {
LLVMAddLoopUnrollAndJamPass(PM);
}

#if LLVM_VERSION_MAJOR < 15
API_EXPORT(void)
LLVMPY_AddLoopUnswitchPass(LLVMPassManagerRef PM, bool optimizeForSize,

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For reference the loop unswitch pass has been renamed to SimpleLoopUnswitchPass in the new pass manager (https://reviews.llvm.org/D124376). Naturally to enable this we need to move to NPM so it makes sense that this is disabled for now but it can come back with NPM.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually createSimpleLoopUnswitchLegacyPass still exists in LLVM-15 so it can be dropped in here without issue.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

API_EXPORT(void)
LLVMPY_AddLoopUnswitchPass(LLVMPassManagerRef PM, bool optimizeForSize,
                           bool hasBranchDivergence) {
#if LLVM_VERSION_MAJOR < 15
    unwrap(PM)->add(
        createLoopUnswitchPass(optimizeForSize, hasBranchDivergence));
#else
    unwrap(PM)->add(
        createSimpleLoopUnswitchLegacyPass(optimizeForSize));
#endif
}

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for finding this, I have updated the code.

bool hasBranchDivergence) {
unwrap(PM)->add(
createLoopUnswitchPass(optimizeForSize, hasBranchDivergence));
}
#endif

API_EXPORT(void)
LLVMPY_AddLowerAtomicPass(LLVMPassManagerRef PM) {
Expand Down
3 changes: 3 additions & 0 deletions ffi/value.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@

// the following is needed for WriteGraph()
#include "llvm/Analysis/CFGPrinter.h"
#if LLVM_VERSION_MAJOR > 14
#include "llvm/Support/GraphWriter.h"
#endif

/* An iterator around a attribute list, including the stop condition */
struct AttributeListIterator {
Expand Down
24 changes: 19 additions & 5 deletions llvmlite/binding/passmanagers.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,16 @@
from collections import namedtuple
from enum import IntFlag
from llvmlite.binding import ffi
from llvmlite.binding.initfini import llvm_version_info
import os
from tempfile import mkstemp
from llvmlite.binding.common import _encode_string

_prunestats = namedtuple('PruneStats',
('basicblock diamond fanout fanout_raise'))

llvm_version_major = llvm_version_info[0]


class PruneStats(_prunestats):
""" Holds statistics from reference count pruning.
Expand Down Expand Up @@ -258,6 +261,8 @@ def add_arg_promotion_pass(self, max_elements=3):

LLVM 14: `llvm::createArgumentPromotionPass`
""" # noqa E501
if llvm_version_major > 14:
raise RuntimeError('ArgumentPromotionPass unavailable in LLVM > 14')
ffi.lib.LLVMPY_AddArgPromotionPass(self, max_elements)

def add_break_critical_edges_pass(self):
Expand Down Expand Up @@ -467,6 +472,8 @@ def add_loop_unswitch_pass(self,

LLVM 14: `llvm::createLoopUnswitchPass`
""" # noqa E501
if llvm_version_major > 14:
raise RuntimeError('LoopUnswitchPass unavailable in LLVM > 14')
ffi.lib.LLVMPY_AddLoopUnswitchPass(self,
optimize_for_size,
has_branch_divergence)
Expand Down Expand Up @@ -866,7 +873,11 @@ def run_with_remarks(self, function, remarks_format='yaml',
ffi.lib.LLVMPY_AddScalarEvolutionAAPass.argtypes = [ffi.LLVMPassManagerRef]
ffi.lib.LLVMPY_AddAggressiveDCEPass.argtypes = [ffi.LLVMPassManagerRef]
ffi.lib.LLVMPY_AddAlwaysInlinerPass.argtypes = [ffi.LLVMPassManagerRef, c_bool]
ffi.lib.LLVMPY_AddArgPromotionPass.argtypes = [ffi.LLVMPassManagerRef, c_uint]

if llvm_version_major < 15:
ffi.lib.LLVMPY_AddArgPromotionPass.argtypes = [
ffi.LLVMPassManagerRef, c_uint]

ffi.lib.LLVMPY_AddBreakCriticalEdgesPass.argtypes = [ffi.LLVMPassManagerRef]
ffi.lib.LLVMPY_AddDeadStoreEliminationPass.argtypes = [
ffi.LLVMPassManagerRef]
Expand All @@ -883,10 +894,13 @@ def run_with_remarks(self, function, remarks_format='yaml',
ffi.lib.LLVMPY_AddLoopSimplificationPass.argtypes = [ffi.LLVMPassManagerRef]
ffi.lib.LLVMPY_AddLoopUnrollPass.argtypes = [ffi.LLVMPassManagerRef]
ffi.lib.LLVMPY_AddLoopUnrollAndJamPass.argtypes = [ffi.LLVMPassManagerRef]
ffi.lib.LLVMPY_AddLoopUnswitchPass.argtypes = [
ffi.LLVMPassManagerRef,
c_bool,
c_bool]

if llvm_version_major < 15:
ffi.lib.LLVMPY_AddLoopUnswitchPass.argtypes = [
ffi.LLVMPassManagerRef,
c_bool,
c_bool]

ffi.lib.LLVMPY_AddLowerAtomicPass.argtypes = [ffi.LLVMPassManagerRef]
ffi.lib.LLVMPY_AddLowerInvokePass.argtypes = [ffi.LLVMPassManagerRef]
ffi.lib.LLVMPY_AddLowerSwitchPass.argtypes = [ffi.LLVMPassManagerRef]
Expand Down
Loading