Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions cuda_bindings/requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,4 @@ tomli; python_version < "3.11"
versioneer==0.29
wheel
pywin32; sys_platform == 'win32'
# llvmlite # Uncomment to generate MINIMAL_NVVMIR_BITCODE_STATIC for test_nvvm.py (see PR #443).
198 changes: 146 additions & 52 deletions cuda_bindings/tests/test_nvvm.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,23 @@
#
# SPDX-License-Identifier: LicenseRef-NVIDIA-SOFTWARE-LICENSE

import base64
import binascii
import re
import textwrap
from contextlib import contextmanager

import pytest

from cuda.bindings import nvvm

MINIMAL_NVVMIR_FIXTURE_PARAMS = ["txt", "bitcode_static"]
try:
import llvmlite.binding as llvmlite_binding # Optional test dependency.
except ImportError:
llvmlite_binding = None
else:
MINIMAL_NVVMIR_FIXTURE_PARAMS.append("bitcode_dynamic")

MINIMAL_NVVMIR_TXT = b"""\
target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-i128:128:128-f32:32:32-f64:64:64-v16:16:16-v32:32:32-v64:64:64-v128:128:128-n16:32:64"

Expand All @@ -24,56 +33,141 @@
!0 = !{void ()* @kernel, !"kernel", i32 1}

!nvvmir.version = !{!1}
!1 = !{i32 2, i32 0, i32 3, i32 1}
!1 = !{i32 %d, i32 0, i32 %d, i32 0}
""" # noqa: E501

# Equivalent to MINIMAL_NVVMIR_TXT
MINIMAL_NVVMIR_BITCODE = base64.b64decode("""
QkPA3jUUAAAFAAAAYgwwJElZvmbu034tRAEyBQAAAAAhDAAAJAEAAAsCIQACAAAAEwAAAAeBI5FB
yARJBhAyOZIBhAwlBQgZHgSLYoAMRQJCkgtCZBAyFDgIGEsKMjKISJAUIENGiKUAGTJC5EgOkJEh
xFBBUYGM4YPligQZRgaJIAAACwAAADIiyAggZIUEkyGkhASTIeOEoZAUEkyGjAuEZEwQFCMAJQBl
IGCOAAwAAAAAEyZ3sAd4oAd8sAM6aAN3sId0IId0CIc2GId6IIdw2OAS5dAG8KAHdkAHemAHdKAH
dkAHbZAOcaAHeKAHeNAG6YAHeoAHeoAHbZAOcWAHehAHdqAHcWAHbZAOcyAHejAHcqAHcyAHbZAO
dkAHemAHdKAHdkAHbZAOcSAHeKAHcSAHeKAHcSAHeNAG5jAHcqAHcyAHejAHctAG5mAHdKAHdkAH
emAHdNAG9hAHdqAHcWAHehAHdtAG9jAHcqAHcyAHejAHctAG9mAHdKAHdkAHemAHdNAG9hAHcoAH
ehAHcoAHehAHcoAHbeAOcWAHejAHcqAHdkAHGiEMGTFIgzDA8jdVxSCRvyxDIsAIAAAAAAAAAAAA
AEBig0BRlAAAgCwQBgAAADIemAwZEUyQjAkmR8YEQ2IJFMEIQBkAALEYAABtAAAAMwiAHMThHGYU
AT2IQziEw4xCgAd5eAdzmHEM5gAP7RAO9IAOMwxCHsLBHc6hHGYwBT2IQziEgxvMAz3IQz2MAz3M
eIx0cAd7CAd5SIdwcAd6cAN2eIdwIIcZzBEO7JAO4TAPbjAP4/AO8FAOMxDEHd4hHNghHcJhHmYw
iTu8gzvQQzm0Azy8gzyEAzvM8BR2YAd7aAc3aIdyaAc3gIdwkIdwYAd2KAd2+AV2eId3gIdfCIdx
GIdymId5mIEs7vAO7uAO9cAO7DADYsihHOShHMyhHOShHNxhHMohHMSBHcphBtaQQznIQzmYQznI
Qzm4wziUQziIAzuUwy+8gzz8gjvUAzuwwwzHaYdwWIdycIN0aAd4YId0GId0oIcZzlMP7gAP8lAO
5JAO40AP4SAO7FAOMyAoHdzBHsJBHtIhHNyBHtzgHOThHeoBHmYYUTiwQzqcgzvMUCR2YAd7aAc3
YId3eAd4mFFM9JAP8FAOMx5qHsphHOghHd7BHX4BHuShHMwhHfBhBlSFgzjMwzuwQz3QQzn8wjzk
QzuIwzuww4zFCod5mId3GId0CAd6KAdyAAAAAHkgAAAeAAAAYh5IIEOIDBk5GSSQkUDGyMhoIlAI
FDKeGBkhR8iQUQwIBQAABgAAAGtlcm5lbAAAIwgCMIJABCMIhDCCQAwjCAQxwyAEwwwEURiDjAQm
KCE3O7s2lzA3tze6MLq0N7e5UQIjHTc7u7Y0ORe7Mrm5tDe3UYIDAAAAqRgAAAsAAAALCnIoh3eA
B3pYcJhDPbjDOLBDOdDDguYcxqEN6EEewsEd5iEd6CEd3sEdANEQAAAGAAAAB8w8pIM7nAM7lAM9
oIM8lEM4kMMBAAAAYSAAAAYAAAATBAGGAwEAAAIAAAAHUBDNFGEAAAAAAABxIAAAAwAAADIOECKE
AKACAAAAAAAAAABlDAAAHQAAABIDlOgAAAAAAAAAAAYAAAAFAAAARAAAAAEAAABQAAAAAAAAAFAA
AAABAAAAaAAAAAAAAAALAAAAEwAAAB4AAAARAAAALwAAAAAAAAAAAAAAAQAAAAAAAAAAAAAABgAA
AAAAAAAGAAAA/////wAkAAAAAAAAXQwAAA8AAAASA5RvAAAAAGtlcm5lbDUuMC4xbnZwdHg2NC1u
dmlkaWEtY3VkYW1pbmltYWxfbnZ2bWlyLmxsAAAAAAA=
""")
# To regenerate, pull and start a docker container:
# docker pull centos/llvm-toolset-7-centos7
# docker run -it centos/llvm-toolset-7-centos7 /bin/bash
# In the docker container, copy MINIMAL_NVVMIR_TXT to a file with name minimal_nvvmir.ll
# Then run:
# llvm-as minimal_nvvmir.ll -o minimal_nvvmir.bc
# Save this to encode.py:
# import base64, sys, textwrap
# bitcode = open(sys.argv[1], "rb").read()
# encoded_bitcode = base64.b64encode(bitcode).decode("ascii")
# wrapped_base64 = "\n".join(textwrap.wrap(encoded_bitcode, width=76))
# print(wrapped_base64)
# Then run:
# python encode.py minimal_nvvmir.bc


@pytest.fixture(params=["txt", "bitcode"])
MINIMAL_NVVMIR_BITCODE_STATIC = {
(1, 3): # (major, debug_major)
"4243c0de3514000005000000620c30244a59be669dfbb4bf0b51804c01000000210c00007f010000"
"0b02210002000000160000000781239141c80449061032399201840c250508191e048b62800c4502"
"42920b42641032143808184b0a3232884870c421234412878c1041920264c808b1142043468820c9"
"01323284182a282a90317cb05c9120c3c8000000892000000b0000003222c80820624600212b2498"
"0c212524980c19270c85a4906032645c20246382a01801300128030173046000132677b00778a007"
"7cb0033a680377b0877420877408873618877a208770d8e012e5d006f0a0077640077a600774a007"
"7640076d900e71a00778a00778d006e980077a80077a80076d900e7160077a100776a0077160076d"
"900e7320077a300772a0077320076d900e7640077a600774a0077640076d900e71200778a0077120"
"0778a00771200778d006e6300772a0077320077a300772d006e6600774a0077640077a600774d006"
"f6100776a0077160077a100776d006f6300772a0077320077a300772d006f6600774a0077640077a"
"600774d006f610077280077a10077280077a10077280076de00e7160077a300772a0077640071a21"
"4c0e11de9c2e4fbbcfbe211560040000000000000000000000000620b141a0e86000004016080000"
"06000000321e980c19114c908c092647c6044362098c009401000000b1180000ac0000003308801c"
"c4e11c6614013d88433884c38c4280077978077398710ce6000fed100ef4800e330c421ec2c11dce"
"a11c6630053d88433884831bcc033dc8433d8c033dcc788c7470077b08077948877070077a700376"
"788770208719cc110eec900ee1300f6e300fe3f00ef0500e3310c41dde211cd8211dc2611e663089"
"3bbc833bd04339b4033cbc833c84033bccf0147660077b6807376887726807378087709087706007"
"76280776f8057678877780875f08877118877298877998812ceef00eeee00ef5c00eec300362c8a1"
"1ce4a11ccca11ce4a11cdc611cca211cc4811dca6106d6904339c84339984339c84339b8c3389443"
"3888033b94c32fbc833cfc823bd4033bb0c30cc7698770588772708374680778608774188774a087"
"19ce530fee000ff2500ee4900ee3400fe1200eec500e3320281ddcc11ec2411ed2211cdc811edce0"
"1ce4e11dea011e66185138b0433a9c833bcc50247660077b68073760877778077898514cf4900ff0"
"500e331e6a1eca611ce8211ddec11d7e011ee4a11ccc211df0610654858338ccc33bb0433dd04339"
"fcc23ce4433b88c33bb0c38cc50a877998877718877408077a28077298815ce3100eecc00ee5500e"
"f33023c1d2411ee4e117d8e11dde011e6648193bb0833db4831b84c3388c4339ccc33cb8c139c8c3"
"3bd4033ccc48b471080776600771088771588719dbc60eec600fede006f0200fe5300fe5200ff650"
"0e6e100ee3300ee5300ff3e006e9e00ee4500ef83023e2ec611cc2811dd8e117ec211de6211dc421"
"1dd8211de8211f66209d3bbc433db80339948339cc58bc7070077778077a08077a488777708719cb"
"e70eef300fe1e00ee9400fe9a00fe530c3010373a8077718875f988770708774a08774d087729881"
"844139e0c338b0433d904339cc40c4a01dcaa11de0411edec11c662463300ee1c00eec300fe9400f"
"e5000000792000001d000000721e482043880c19097232482023818c9191d144a01028643c313242"
"8e9021a318100a00060000006b65726e656c0000230802308240042308843082400c330c4230cc40"
"0c4441c84860821272b3b36b730973737ba30ba34b7b739b1b2528d271b3b36b4b9373b12b939b4b"
"7b731b2530000000a9180000250000000b0a7228877780077a587098433db8c338b04339d0c382e6"
"1cc6a10de8411ec2c11de6211de8211ddec11d1634e3600ee7500fe1200fe4400fe1200fe7500ef4"
"b08081077928877060077678877108077a28077258709cc338b4013ba4833d94c3026b1cd8211cdc"
"e11cdc201ce4611cdc201ce8811ec2611cd0a11cc8611cc2811dd861c1010ff4200fe1500ff4800e"
"00000000d11000000600000007cc3ca4833b9c033b94033da0833c94433890c30100000061200000"
"06000000130481860301000002000000075010cd14610000000000007120000003000000320e1022"
"8400fb020000000000000000650c00001f000000120394f000000000030000000600000006000000"
"4c000000010000005800000000000000580000000100000070000000000000000c00000013000000"
"1f000000080000000600000000000000700000000000000000000000010000000000000000000000"
"060000000000000006000000ffffffff00240000000000005d0c00000d0000001203946700000000"
"6b65726e656c31352e302e376e7670747836342d6e76696469612d637564613c737472696e673e00"
"00000000",
(2, 3): # (major, debug_major)
"4243c0de3514000005000000620c30244a59be669dfbb4bf0b51804c01000000210c000080010000"
"0b02210002000000160000000781239141c80449061032399201840c250508191e048b62800c4502"
"42920b42641032143808184b0a3232884870c421234412878c1041920264c808b1142043468820c9"
"01323284182a282a90317cb05c9120c3c8000000892000000b0000003222c80820624600212b2498"
"0c212524980c19270c85a4906032645c20246382a01801300128030173046000132677b00778a007"
"7cb0033a680377b0877420877408873618877a208770d8e012e5d006f0a0077640077a600774a007"
"7640076d900e71a00778a00778d006e980077a80077a80076d900e7160077a100776a0077160076d"
"900e7320077a300772a0077320076d900e7640077a600774a0077640076d900e71200778a0077120"
"0778a00771200778d006e6300772a0077320077a300772d006e6600774a0077640077a600774d006"
"f6100776a0077160077a100776d006f6300772a0077320077a300772d006f6600774a0077640077a"
"600774d006f610077280077a10077280077a10077280076de00e7160077a300772a0077640071a21"
"4c0e11de9c2e4fbbcfbe211560040000000000000000000000000620b141a0286100004016080000"
"06000000321e980c19114c908c092647c60443620914c10840190000b1180000ac0000003308801c"
"c4e11c6614013d88433884c38c4280077978077398710ce6000fed100ef4800e330c421ec2c11dce"
"a11c6630053d88433884831bcc033dc8433d8c033dcc788c7470077b08077948877070077a700376"
"788770208719cc110eec900ee1300f6e300fe3f00ef0500e3310c41dde211cd8211dc2611e663089"
"3bbc833bd04339b4033cbc833c84033bccf0147660077b6807376887726807378087709087706007"
"76280776f8057678877780875f08877118877298877998812ceef00eeee00ef5c00eec300362c8a1"
"1ce4a11ccca11ce4a11cdc611cca211cc4811dca6106d6904339c84339984339c84339b8c3389443"
"3888033b94c32fbc833cfc823bd4033bb0c30cc7698770588772708374680778608774188774a087"
"19ce530fee000ff2500ee4900ee3400fe1200eec500e3320281ddcc11ec2411ed2211cdc811edce0"
"1ce4e11dea011e66185138b0433a9c833bcc50247660077b68073760877778077898514cf4900ff0"
"500e331e6a1eca611ce8211ddec11d7e011ee4a11ccc211df0610654858338ccc33bb0433dd04339"
"fcc23ce4433b88c33bb0c38cc50a877998877718877408077a28077298815ce3100eecc00ee5500e"
"f33023c1d2411ee4e117d8e11dde011e6648193bb0833db4831b84c3388c4339ccc33cb8c139c8c3"
"3bd4033ccc48b471080776600771088771588719dbc60eec600fede006f0200fe5300fe5200ff650"
"0e6e100ee3300ee5300ff3e006e9e00ee4500ef83023e2ec611cc2811dd8e117ec211de6211dc421"
"1dd8211de8211f66209d3bbc433db80339948339cc58bc7070077778077a08077a488777708719cb"
"e70eef300fe1e00ee9400fe9a00fe530c3010373a8077718875f988770708774a08774d087729881"
"844139e0c338b0433d904339cc40c4a01dcaa11de0411edec11c662463300ee1c00eec300fe9400f"
"e5000000792000001e000000721e482043880c19097232482023818c9191d144a01028643c313242"
"8e9021a318100a00060000006b65726e656c0000230802308240042308843082400c23080431c320"
"04c30c045118858c04262821373bbb36973037b737ba30bab437b7b95102231d373bbbb6343917bb"
"32b9b9b437b7518203000000a9180000250000000b0a7228877780077a587098433db8c338b04339"
"d0c382e61cc6a10de8411ec2c11de6211de8211ddec11d1634e3600ee7500fe1200fe4400fe1200f"
"e7500ef4b08081077928877060077678877108077a28077258709cc338b4013ba4833d94c3026b1c"
"d8211cdce11cdc201ce4611cdc201ce8811ec2611cd0a11cc8611cc2811dd861c1010ff4200fe150"
"0ff4800e00000000d11000000600000007cc3ca4833b9c033b94033da0833c94433890c301000000"
"6120000006000000130481860301000002000000075010cd14610000000000007120000003000000"
"320e10228400fc020000000000000000650c00001f000000120394f0000000000300000006000000"
"060000004c000000010000005800000000000000580000000100000070000000000000000c000000"
"130000001f0000000800000006000000000000007000000000000000000000000100000000000000"
"00000000060000000000000006000000ffffffff00240000000000005d0c00000d00000012039467"
"000000006b65726e656c31352e302e376e7670747836342d6e76696469612d637564613c73747269"
"6e673e0000000000",
}

MINIMAL_NVVMIR_CACHE = {}


@pytest.fixture(params=MINIMAL_NVVMIR_FIXTURE_PARAMS)
def minimal_nvvmir(request):
return MINIMAL_NVVMIR_TXT if request.param == "txt" else MINIMAL_NVVMIR_BITCODE
for pass_counter in range(2):
nvvmir = MINIMAL_NVVMIR_CACHE.get(request.param, -1)
if nvvmir != -1:
if nvvmir is None:
pytest.skip(f"UNAVAILABLE: {request.param}")
return nvvmir
if pass_counter:
raise AssertionError("This code path is meant to be unreachable.")
# Build cache entries, then try again (above).
major, minor, debug_major, debug_minor = nvvm.ir_version()
txt = MINIMAL_NVVMIR_TXT % (major, debug_major)
if llvmlite_binding is None:
bitcode_dynamic = None
else:
bitcode_dynamic = llvmlite_binding.parse_assembly(txt.decode()).as_bitcode()
bitcode_static = MINIMAL_NVVMIR_BITCODE_STATIC.get((major, debug_major))
if bitcode_static is not None:
bitcode_static = binascii.unhexlify(bitcode_static)
MINIMAL_NVVMIR_CACHE["txt"] = txt
MINIMAL_NVVMIR_CACHE["bitcode_dynamic"] = bitcode_dynamic
MINIMAL_NVVMIR_CACHE["bitcode_static"] = bitcode_static
if bitcode_static is None:
if bitcode_dynamic is None:
raise RuntimeError("Please `pip install llvmlite` to generate `bitcode_static` (see PR #443)")
bitcode_hex = binascii.hexlify(bitcode_dynamic).decode("ascii")
print("\n\nMINIMAL_NVVMIR_BITCODE_STATIC = { # PLEASE ADD TO test_nvvm.py")
print(f" ({major}, {debug_major}): # (major, debug_major)")
lines = textwrap.wrap(bitcode_hex, width=80)
for line in lines[:-1]:
print(f' "{line}"')
print(f' "{lines[-1]}",')
print("}\n", flush=True)


@pytest.fixture(params=[nvvm.compile_program, nvvm.verify_program])
Expand Down Expand Up @@ -103,13 +197,13 @@ def get_program_log(prog):
def test_nvvm_version():
ver = nvvm.version()
assert len(ver) == 2
assert ver >= (2, 0)
assert ver >= (1, 0)


def test_nvvm_ir_version():
ver = nvvm.ir_version()
assert len(ver) == 4
assert ver >= (2, 0, 3, 1)
assert ver >= (1, 0, 0, 0)


def test_create_and_destroy():
Expand Down Expand Up @@ -167,7 +261,7 @@ def test_get_buffer_empty(get_size, get_buffer):


@pytest.mark.parametrize("options", [[], ["-opt=0"], ["-opt=3", "-g"]])
def test_compile_program_with_minimal_nnvm_ir(minimal_nvvmir, options):
def test_compile_program_with_minimal_nvvm_ir(minimal_nvvmir, options):
with nvvm_program() as prog:
nvvm.add_module_to_program(prog, minimal_nvvmir, len(minimal_nvvmir), "FileNameHere.ll")
try:
Expand All @@ -187,7 +281,7 @@ def test_compile_program_with_minimal_nnvm_ir(minimal_nvvmir, options):


@pytest.mark.parametrize("options", [[], ["-opt=0"], ["-opt=3", "-g"]])
def test_verify_program_with_minimal_nnvm_ir(minimal_nvvmir, options):
def test_verify_program_with_minimal_nvvm_ir(minimal_nvvmir, options):
with nvvm_program() as prog:
nvvm.add_module_to_program(prog, minimal_nvvmir, len(minimal_nvvmir), "FileNameHere.ll")
nvvm.verify_program(prog, len(options), options)
Loading