From 7172f0567b68d7786aa678a3aa92e2703546ba0c Mon Sep 17 00:00:00 2001 From: Jan Vesely Date: Tue, 6 Aug 2024 20:24:58 -0400 Subject: [PATCH 1/4] llvm/helpers: Assert on invalid floating point conversion Signed-off-by: Jan Vesely --- psyneulink/core/llvm/helpers.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/psyneulink/core/llvm/helpers.py b/psyneulink/core/llvm/helpers.py index 2eae0e69974..175703458ac 100644 --- a/psyneulink/core/llvm/helpers.py +++ b/psyneulink/core/llvm/helpers.py @@ -319,8 +319,7 @@ def convert_type(builder, val, t): val = builder.fptrunc(val, ir.FloatType()) return builder.fptrunc(val, t) else: - assert val.type == t - return val + assert False, "Unknown float conversion: {} -> {}".format(val.type, t) assert False, "Unknown type conversion: {} -> {}".format(val.type, t) From c8fcf8b79254f19c6346dcb2c01f1d17eaab22b1 Mon Sep 17 00:00:00 2001 From: Jan Vesely Date: Tue, 6 Aug 2024 23:53:08 -0400 Subject: [PATCH 2/4] llvm: Use zero extend to promote integers Add integer conversion tests. Signed-off-by: Jan Vesely --- psyneulink/core/llvm/helpers.py | 2 +- tests/llvm/test_helpers.py | 47 ++++++++++++++++++++++++++++++--- 2 files changed, 44 insertions(+), 5 deletions(-) diff --git a/psyneulink/core/llvm/helpers.py b/psyneulink/core/llvm/helpers.py index 175703458ac..9ed6cc1701d 100644 --- a/psyneulink/core/llvm/helpers.py +++ b/psyneulink/core/llvm/helpers.py @@ -292,7 +292,7 @@ def convert_type(builder, val, t): return builder.trunc(val, t) elif val.type.width < t.width: # Python integers are signed - return builder.sext(val, t) + return builder.zext(val, t) else: assert False, "Unknown integer conversion: {} -> {}".format(val.type, t) diff --git a/tests/llvm/test_helpers.py b/tests/llvm/test_helpers.py index 00696744eb1..cd2227ded05 100644 --- a/tests/llvm/test_helpers.py +++ b/tests/llvm/test_helpers.py @@ -193,11 +193,10 @@ def test_helper_all_close(mode, var1, var2, atol, rtol): builder.store(res, out) builder.ret_void() + bin_f = pnlvm.LLVMBinaryFunction.get(custom_name) + res = bin_f.np_buffer_for_arg(2) ref = np.allclose(vec1, vec2, **tolerance) - res = np.array(5, dtype=np.uint32) - - bin_f = pnlvm.LLVMBinaryFunction.get(custom_name) if mode == 'CPU': bin_f(vec1, vec2, res) @@ -558,7 +557,7 @@ def test_helper_convert_fp_type(t1, t2, mode, val): np_dt1, np_dt2 = (np.dtype(bin_f.np_arg_dtypes[i]) for i in (0, 1)) # instantiate value, result and reference - x = np.asfarray(val, dtype=bin_f.np_arg_dtypes[0]) + x = np.asfarray(val, dtype=np_dt1) y = bin_f.np_buffer_for_arg(1) ref = x.astype(np_dt2) @@ -568,3 +567,43 @@ def test_helper_convert_fp_type(t1, t2, mode, val): bin_f.cuda_wrap_call(x, y) np.testing.assert_allclose(y, ref, equal_nan=True) + + +_int_types = [ir.IntType(64), ir.IntType(32), ir.IntType(16), ir.IntType(8)] + + +@pytest.mark.llvm +@pytest.mark.parametrize('mode', ['CPU', pytest.helpers.cuda_param('PTX')]) +@pytest.mark.parametrize('t1', _int_types, ids=str) +@pytest.mark.parametrize('t2', _int_types, ids=str) +@pytest.mark.parametrize('val', [0, 1, -1, 127, -128, 255, -32768, 32767, 65535, np.iinfo(np.int32).min, np.iinfo(np.int32).max]) +def test_helper_convert_int_type(t1, t2, mode, val): + with pnlvm.LLVMBuilderContext.get_current() as ctx: + func_ty = ir.FunctionType(ir.VoidType(), [t1.as_pointer(), t2.as_pointer()]) + custom_name = ctx.get_unique_name("int_convert") + function = ir.Function(ctx.module, func_ty, name=custom_name) + x, y = function.args + block = function.append_basic_block(name="entry") + builder = ir.IRBuilder(block) + + x_val = builder.load(x) + conv_x = pnlvm.helpers.convert_type(builder, x_val, y.type.pointee) + builder.store(conv_x, y) + builder.ret_void() + + bin_f = pnlvm.LLVMBinaryFunction.get(custom_name) + + # Get the argument numpy dtype + np_dt1, np_dt2 = (np.dtype(bin_f.np_arg_dtypes[i]) for i in (0, 1)) + + # instantiate value, result and reference + x = np.asarray(val).astype(np_dt1) + y = bin_f.np_buffer_for_arg(1) + ref = x.astype(np_dt2) + + if mode == 'CPU': + bin_f(x, y) + else: + bin_f.cuda_wrap_call(x, y) + + np.testing.assert_array_equal(y, ref) From eae133f2f1abe4ef2c1acc1baaaf62e2976e410e Mon Sep 17 00:00:00 2001 From: Jan Vesely Date: Wed, 7 Aug 2024 11:13:04 -0400 Subject: [PATCH 3/4] llvm/helpers: Always assume that the Treshold target is an array Signed-off-by: Jan Vesely --- psyneulink/core/llvm/helpers.py | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/psyneulink/core/llvm/helpers.py b/psyneulink/core/llvm/helpers.py index 9ed6cc1701d..d0958200ec0 100644 --- a/psyneulink/core/llvm/helpers.py +++ b/psyneulink/core/llvm/helpers.py @@ -757,14 +757,16 @@ def generate_sched_condition(self, builder, condition, cond_ptr, node, node_state = builder.gep(nodes_states, [self.ctx.int32_ty(0), self.ctx.int32_ty(node_idx)]) param_ptr = get_state_ptr(builder, target, node_state, param) - if isinstance(param_ptr.type.pointee, ir.ArrayType): - if indices is None: - indices = [0, 0] - elif isinstance(indices, TimeScale): - indices = [indices.value] - - indices = [self.ctx.int32_ty(x) for x in [0] + list(indices)] - param_ptr = builder.gep(param_ptr, indices) + # parameters in state include history of at least one element + # so they are always arrays. + assert isinstance(param_ptr.type.pointee, ir.ArrayType) + + if indices is None: + indices = [0, 0] + elif isinstance(indices, TimeScale): + indices = [indices.value] + + param_ptr = builder.gep(param_ptr, [self.ctx.int32_ty(x) for x in [0] + list(indices)]) val = builder.load(param_ptr) val = convert_type(builder, val, ir.DoubleType()) From db02a8ec5ccebcb0b62819f4fb9144aee54f6550 Mon Sep 17 00:00:00 2001 From: Jan Vesely Date: Wed, 7 Aug 2024 11:16:06 -0400 Subject: [PATCH 4/4] llvm/helpers: Assert if printf is not found Compiled printf is only available as debugging measure, so warnings are not useful. Signed-off-by: Jan Vesely --- psyneulink/core/llvm/helpers.py | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/psyneulink/core/llvm/helpers.py b/psyneulink/core/llvm/helpers.py index d0958200ec0..d4fcc8cd2f5 100644 --- a/psyneulink/core/llvm/helpers.py +++ b/psyneulink/core/llvm/helpers.py @@ -408,16 +408,12 @@ def printf(builder, fmt, *args, override_debug=False): #FIXME: Fix builtin printf and use that instead of this libc_name = "msvcrt" if sys.platform == "win32" else "c" libc = util.find_library(libc_name) - if libc is None: - warnings.warn("Standard libc library not found, 'printf' not available!") - return + assert libc is not None, "Standard libc library not found" llvm.load_library_permanently(libc) # Address will be none if the symbol is not found printf_address = llvm.address_of_symbol("printf") - if printf_address is None: - warnings.warn("'printf' symbol not found in libc, 'printf' not available!") - return + assert printf_address is not None, "'printf' symbol not found in {}".format(libc) # Direct pointer constants don't work printf_ty = ir.FunctionType(ir.IntType(32), [ir.IntType(8).as_pointer()], var_arg=True)