Skip to content
Closed
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
8 changes: 7 additions & 1 deletion devito/passes/clusters/cse.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
from devito.finite_differences.differentiable import IndexSum
from devito.ir import Cluster, Scope, cluster_pass
from devito.symbolics import (
DefFunction, Reserved, estimate_cost, q_leaf, q_terminal, search
DefFunction, IndexedPointer, Reserved, estimate_cost, q_leaf, q_terminal, search
)
from devito.symbolics.manipulation import _uxreplace
from devito.tools import DAG, as_list, as_tuple, extract_dtype, frozendict
Expand Down Expand Up @@ -418,11 +418,17 @@ def _(expr):


@_catch.register(Indexed)
@_catch.register(IndexedPointer)
@_catch.register(Symbol)
@_catch.register(Reserved)
def _(expr):
"""
Handler for objects preventing CSE to propagate through their arguments.

For IndexedPointer (e.g. `f_vec->sizes[(time / ct0f) + ...]`) this also
keeps integer index expressions out of a floating-point cluster's CSE
temporaries, which `cse_dtype` would otherwise declare as floating-point
and thus produce non-integral array subscripts.
"""
return {}

Expand Down
29 changes: 28 additions & 1 deletion tests/test_cse.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
from devito.ir import Conditional, DummyEq, FindNodes, FindSymbols
from devito.ir.support import generator
from devito.passes.clusters.cse import CTemp, _cse
from devito.symbolics import DefFunction, indexify
from devito.symbolics import DefFunction, FieldFromPointer, IndexedPointer, indexify
from devito.types import Array, Symbol, Temp


Expand Down Expand Up @@ -154,6 +154,33 @@ def test_deffunction_not_captured():
assert processed == exprs


def test_indexedpointer_index_not_captured():
"""
The index of an IndexedPointer (e.g. `f_vec->sizes[...]`) must not be
CSE-captured: in a floating-point cluster `cse_dtype` would bind the
integer index to a floating-point temporary, yielding a non-integral
array subscript that does not compile (nvcc, hipcc).
"""
time = Symbol(name='time', dtype=np.int32)
fac = Symbol(name='fac', dtype=np.int32)
vec = Symbol(name='f_vec', dtype=np.int32)
a = CTemp(name='a', dtype=np.float32)
b = CTemp(name='b', dtype=np.float32)

index = time/fac + 2*time
sizes = IndexedPointer(FieldFromPointer('sizes', vec), index)
offs = IndexedPointer(FieldFromPointer('offs', vec), index)
exprs = [DummyEq(a, sizes + 1.), DummyEq(b, offs + sizes)]

counter = generator()
make = lambda e: CTemp(name=f'r{counter()}', dtype=np.float32)
processed = _cse(exprs, make)

for e in processed:
for i in e.find(IndexedPointer):
assert not any(isinstance(s, CTemp) for s in i.index.free_symbols)


def test_w_conditionals():
grid = Grid(shape=(10, 10, 10))
x, _, _ = grid.dimensions
Expand Down
Loading