Skip to content

Commit

Permalink
implement hoistable getitem for typed-list
Browse files Browse the repository at this point in the history
This implements exporting the base pointer of the typed-list `items`
array  and then implements `getitem` in builder code. This has the
advantage, that the `getitem` can in principle be hoisted / loop lifted.
  • Loading branch information
esc committed Feb 3, 2020
1 parent 9447fa4 commit 799eff4
Show file tree
Hide file tree
Showing 4 changed files with 56 additions and 2 deletions.
1 change: 1 addition & 0 deletions numba/_helpermod.c
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,7 @@ build_c_helpers_dict(void)
declmethod(list_free);
declmethod(list_length);
declmethod(list_allocated);
declmethod(list_base_ptr);
declmethod(list_setitem);
declmethod(list_getitem);
declmethod(list_append);
Expand Down
10 changes: 10 additions & 0 deletions numba/cext/listobject.c
Original file line number Diff line number Diff line change
Expand Up @@ -227,6 +227,16 @@ numba_list_allocated(NB_List *lp) {
return lp->allocated;
}

/* Return the base pointer of the list items
*
* lp: a list
*/
char *
numba_list_base_ptr(NB_List *lp)
{
return lp->items;
}

/* Set an item in a list.
*
* lp: a list
Expand Down
3 changes: 3 additions & 0 deletions numba/cext/listobject.h
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,9 @@ numba_list_length(NB_List *lp);
NUMBA_EXPORT_FUNC(Py_ssize_t)
numba_list_allocated(NB_List *lp);

NUMBA_EXPORT_FUNC(char *)
numba_list_base_ptr(NB_List *lp);

NUMBA_EXPORT_FUNC(int)
numba_list_setitem(NB_List *lp, Py_ssize_t index, const char *item);

Expand Down
44 changes: 42 additions & 2 deletions numba/listobject.py
Original file line number Diff line number Diff line change
Expand Up @@ -555,8 +555,48 @@ def handle_slice(l, s):


@intrinsic
def _list_getitem(typingctx, l, index):
return _list_getitem_pop_helper(typingctx, l, index, 'getitem')
def _list_getitem(typingctx, l_ty, index_ty):
resty = types.Tuple([types.int32, types.Optional(l_ty.item_type)])
sig = resty(l_ty, index_ty)

def codegen(context, builder, sig, args):
[tl, tindex] = sig.args
[l, index] = args
fnty = ir.FunctionType(
ll_voidptr_type,
[ll_list_type],
)
fn = builder.module.get_or_insert_function(fnty,
name='numba_list_base_ptr')
fn.attributes.add('alwaysinline')
fn.attributes.add('readonly')

lp = _container_get_data(context, builder, tl, l)

base_ptr = builder.call(
fn,
[lp,],
)

llty = context.get_data_type(tl.item_type)
casted_base_ptr = builder.bitcast(base_ptr, llty.as_pointer())

item_ptr = cgutils.gep(builder, casted_base_ptr, index)

out = context.make_optional_none(builder, tl.item_type)
pout = cgutils.alloca_once_value(builder, out)

dm_item = context.data_model_manager[tl.item_type]
item = dm_item.load_from_data_pointer(builder, item_ptr)
context.nrt.incref(builder, tl.item_type, item)
# probably need to actually do something about Optional
loaded = context.make_optional_value(builder, tl.item_type, item)
builder.store(loaded, pout)

out = builder.load(pout)
return context.make_tuple(builder, resty, [ll_status(0), out])

return sig, codegen


@intrinsic
Expand Down

0 comments on commit 799eff4

Please sign in to comment.