@@ -873,12 +873,25 @@ def _uniform_tuple(val: Any, *, rank: int):
873873 return (val ,) * rank
874874
875875
876+ def _check_bounds_to_inbounds (check_bounds : Var , rank : int ) -> tuple [bool , ...]:
877+ check = require_constant_bool (check_bounds )
878+ inbounds = _uniform_tuple (not check , rank = rank )
879+ if not check :
880+ cur_version = Builder .get_current ().ir_ctx .tileiras_version
881+ if cur_version < BytecodeVersion .V_13_4 :
882+ raise TileUnsupportedFeatureError (
883+ f"'check_bounds=False' requires tileiras { BytecodeVersion .V_13_4 .as_string ()} "
884+ f" or later. Current version is { cur_version .as_string ()} ." )
885+ return inbounds
886+
887+
876888@dataclass (eq = False )
877889class TileLoad (Operation , opcode = "tile_load" , memory_effect = MemoryEffect .LOAD ):
878890 latency : Optional [int ] = attribute ()
879891 allow_tma : Optional [bool ] = attribute ()
880892 memory_order : MemoryOrder = attribute (default = MemoryOrder .WEAK )
881893 memory_scope : MemoryScope = attribute (default = MemoryScope .NONE )
894+ inbounds : tuple [bool , ...] = attribute (default = ())
882895 view : Var = operand ()
883896 index : tuple [Var , ...] = operand ()
884897 token : Optional [Var ] = operand (default = None )
@@ -910,14 +923,15 @@ def generate_bytecode(self, ctx: BytecodeContext) -> tuple[bc.Value, bc.Value]:
910923 memory_ordering_semantics = memory_order_to_bytecode [self .memory_order ],
911924 memory_scope = memory_scope_to_bytecode [self .memory_scope ],
912925 optimization_hints = ctx .load_store_hints (self .latency , self .allow_tma ),
913- inbounds = _uniform_tuple (False , rank = len (self .index )),
926+ inbounds = self . inbounds or _uniform_tuple (False , rank = len (self .index )),
914927 )
915928 return res , res_token
916929
917930
918931def _tile_load_impl_inner (array : Var , index_items : tuple [Var , ...], shape : Sequence [int ],
919932 order : Sequence [int ], padding_mode : PaddingMode ,
920933 latency : Var , allow_tma : Var ,
934+ inbounds : tuple [bool , ...] = (),
921935 traversal_steps : Optional [tuple [int , ...]] = None ,
922936 memory_order : MemoryOrder = MemoryOrder .WEAK ,
923937 memory_scope : MemoryScope = MemoryScope .NONE ) -> Var :
@@ -938,7 +952,7 @@ def _tile_load_impl_inner(array: Var, index_items: tuple[Var, ...], shape: Seque
938952 result , _token = add_operation_variadic (TileLoad , (res_ty , TokenTy ()),
939953 view = view , index = index_items , latency = latency ,
940954 allow_tma = allow_tma , memory_order = memory_order ,
941- memory_scope = memory_scope )
955+ memory_scope = memory_scope , inbounds = inbounds )
942956 return reshape (result , shape )
943957
944958
@@ -1009,7 +1023,7 @@ def raw_array_memory_store_offset_impl(self: Var, offset: Var, value: Var,
10091023
10101024@impl (ct .load )
10111025def tile_load_impl (array : Var , index : Var , shape : Var , order : Var ,
1012- padding_mode : Var , latency : Var , allow_tma : Var ,
1026+ padding_mode : Var , check_bounds : Var , latency : Var , allow_tma : Var ,
10131027 memory_order : Var , memory_scope : Var ) -> Var :
10141028 array_ty = require_array_type (array )
10151029 index_ty = require_index_or_index_tuple_type (index )
@@ -1022,11 +1036,12 @@ def tile_load_impl(array: Var, index: Var, shape: Var, order: Var,
10221036 allow_0d_shape = True )
10231037 order = require_constant_axis_order (order , array_ty .ndim )
10241038 padding_mode = require_constant_enum (padding_mode , PaddingMode )
1039+ inbounds = _check_bounds_to_inbounds (check_bounds , array_ty .ndim )
10251040 mem_order = require_constant_enum (memory_order , MemoryOrder )
10261041 mem_scope = require_constant_enum (memory_scope , MemoryScope )
10271042 validate_memory_order_and_scope (mem_order , mem_scope , TileLoad )
10281043 return _tile_load_impl_inner (array , index_items , shape , order , padding_mode , latency , allow_tma ,
1029- memory_order = mem_order , memory_scope = mem_scope )
1044+ inbounds = inbounds , memory_order = mem_order , memory_scope = mem_scope )
10301045
10311046
10321047@dataclass (eq = False )
@@ -1035,6 +1050,7 @@ class TileStore(Operation, opcode="tile_store", memory_effect=MemoryEffect.STORE
10351050 allow_tma : Optional [bool ] = attribute ()
10361051 memory_order : MemoryOrder = attribute (default = MemoryOrder .WEAK )
10371052 memory_scope : MemoryScope = attribute (default = MemoryScope .NONE )
1053+ inbounds : tuple [bool , ...] = attribute (default = ())
10381054 view : Var = operand ()
10391055 index : tuple [Var , ...] = operand ()
10401056 tile : Var = operand ()
@@ -1066,12 +1082,13 @@ def generate_bytecode(self, ctx: BytecodeContext) -> bc.Value:
10661082 memory_ordering_semantics = memory_order_to_bytecode [self .memory_order ],
10671083 memory_scope = memory_scope_to_bytecode [self .memory_scope ],
10681084 optimization_hints = ctx .load_store_hints (self .latency , self .allow_tma ),
1069- inbounds = _uniform_tuple (False , rank = len (self .index ))
1085+ inbounds = self . inbounds or _uniform_tuple (False , rank = len (self .index ))
10701086 )
10711087
10721088
10731089def _tile_store_impl_inner (array : Var , index_items : tuple [Var , ...], tile : Var ,
10741090 order : Sequence [int ], latency : Var , allow_tma : Var ,
1091+ inbounds : tuple [bool , ...] = (),
10751092 traversal_steps : Optional [tuple [int , ...]] = None ,
10761093 memory_order : MemoryOrder = MemoryOrder .WEAK ,
10771094 memory_scope : MemoryScope = MemoryScope .NONE ):
@@ -1092,12 +1109,12 @@ def _tile_store_impl_inner(array: Var, index_items: tuple[Var, ...], tile: Var,
10921109 traversal_steps )
10931110 add_operation (TileStore , TokenTy (), view = view , index = index_items , tile = tile ,
10941111 latency = latency , allow_tma = allow_tma , memory_order = memory_order ,
1095- memory_scope = memory_scope )
1112+ memory_scope = memory_scope , inbounds = inbounds )
10961113
10971114
10981115@impl (ct .store )
10991116def tile_store_impl (array : Var , index : Var , tile : Var , order : Var ,
1100- latency : Var , allow_tma : Var ,
1117+ check_bounds : Var , latency : Var , allow_tma : Var ,
11011118 memory_order : Var , memory_scope : Var ):
11021119 array_ty = require_array_type (array )
11031120 index_ty = require_index_or_index_tuple_type (index )
@@ -1108,11 +1125,12 @@ def tile_store_impl(array: Var, index: Var, tile: Var, order: Var,
11081125
11091126 tile = implicit_cast (tile , array_ty .dtype , "Stored tile is incompatible with array's dtype" )
11101127 order = require_constant_axis_order (order , array_ty .ndim )
1128+ inbounds = _check_bounds_to_inbounds (check_bounds , array_ty .ndim )
11111129 mem_order = require_constant_enum (memory_order , MemoryOrder )
11121130 mem_scope = require_constant_enum (memory_scope , MemoryScope )
11131131 validate_memory_order_and_scope (mem_order , mem_scope , TileStore )
11141132 _tile_store_impl_inner (array , index_items , tile , order , latency , allow_tma ,
1115- memory_order = mem_order , memory_scope = mem_scope )
1133+ inbounds = inbounds , memory_order = mem_order , memory_scope = mem_scope )
11161134
11171135
11181136@dataclass (eq = False )
@@ -3158,23 +3176,27 @@ def tiled_view_num_tiles(self: Var, axis: Var) -> Var:
31583176
31593177
31603178@impl (ct .TiledView .load )
3161- def tiled_view_load_impl (self : Var , index : Var , latency : Var , allow_tma : Var ) -> Var :
3179+ def tiled_view_load_impl (self : Var , index : Var , check_bounds : Var , latency : Var ,
3180+ allow_tma : Var ) -> Var :
31623181 view_ty = require_tiled_view_type (self )
31633182 index_ty = require_index_or_index_tuple_type (index )
31643183 index_items = index .get_aggregate ().items if isinstance (index_ty , TupleTy ) else (index ,)
31653184 if view_ty .ndim != len (index_items ):
31663185 raise TileTypeError (f"Index size { len (index_items )} "
31673186 f" does not match the tiled view rank { view_ty .ndim } " )
31683187
3188+ inbounds = _check_bounds_to_inbounds (check_bounds , view_ty .ndim )
31693189 [array ] = self .get_aggregate ().as_tuple ()
31703190 order = get_default_order (view_ty .ndim )
31713191 return _tile_load_impl_inner (array , index_items , view_ty .tile_shape , order ,
31723192 view_ty .padding_mode , latency , allow_tma ,
3193+ inbounds = inbounds ,
31733194 traversal_steps = view_ty .traversal_steps )
31743195
31753196
31763197@impl (ct .TiledView .store )
3177- def tiled_view_store_impl (self : Var , index : Var , tile : Var , latency : Var , allow_tma : Var ):
3198+ def tiled_view_store_impl (self : Var , index : Var , tile : Var , check_bounds : Var , latency : Var ,
3199+ allow_tma : Var ):
31783200 view_ty = require_tiled_view_type (self )
31793201 index_ty = require_index_or_index_tuple_type (index )
31803202 index_items = index .get_aggregate ().items if isinstance (index_ty , TupleTy ) else (index ,)
@@ -3187,12 +3209,14 @@ def tiled_view_store_impl(self: Var, index: Var, tile: Var, latency: Var, allow_
31873209 raise TileTypeError (f"Tile shape { tile_ty .shape } is not broadcastable"
31883210 f" to the tiled view's tile shape { view_ty .tile_shape } " )
31893211
3212+ inbounds = _check_bounds_to_inbounds (check_bounds , view_ty .ndim )
31903213 tile = broadcast_to (tile , view_ty .tile_shape )
31913214 tile = implicit_cast (tile , view_ty .dtype ,
31923215 "Stored tile is incompatible with tiled view's dtype" )
31933216 [array ] = self .get_aggregate ().as_tuple ()
31943217 order = get_default_order (view_ty .ndim )
31953218 _tile_store_impl_inner (array , index_items , tile , order , latency , allow_tma ,
3219+ inbounds = inbounds ,
31963220 traversal_steps = view_ty .traversal_steps )
31973221
31983222
0 commit comments