@@ -569,7 +569,7 @@ function emit_reduce!(ctx::CGCtx, args, reduce_fn::Symbol)
569569 results = encode_ReduceOp! (cb, [output_tile_type], [input_tv. v], axis, [identity], [scalar_tile_type]) do block_args
570570 acc, elem = block_args[1 ], block_args[2 ]
571571
572- res = encode_reduce_body (cb, scalar_tile_type, acc, elem, reduce_fn, elem_type)
572+ res = encode_binop_body (cb, scalar_tile_type, acc, elem, reduce_fn, elem_type)
573573 encode_YieldOp! (cb, [res])
574574 end
575575
@@ -609,26 +609,18 @@ operation_identity(::Val{:max}, dtype, ::Type{T}) where T <: Integer =
609609 IntegerIdentityVal (to_uint128 (typemin (T)), dtype, T)
610610
611611#= ============================================================================#
612- # Reduce Body Operations
612+ # Binary Operation Body Encoding (shared by reduce and scan)
613613#= ============================================================================#
614- function encode_reduce_body (cb, type, acc, elem, op:: Symbol , :: Type{T} ) where T
614+ function encode_binop_body (cb, type, acc, elem, op:: Symbol , :: Type{T} ) where T
615615 if T <: AbstractFloat
616- if op == :add
617- encode_AddFOp! (cb, type, acc, elem)
618- elseif op == :max
619- encode_MaxFOp! (cb, type, acc, elem)
620- else
621- error (" Unsupported float reduction operation: $op " )
622- end
623- else # Integer
616+ op == :add ? encode_AddFOp! (cb, type, acc, elem) :
617+ op == :max ? encode_MaxFOp! (cb, type, acc, elem) :
618+ error (" Unsupported float operation: $op " )
619+ else
624620 signedness = T <: Signed ? SignednessSigned : SignednessUnsigned
625- if op == :add
626- encode_AddIOp! (cb, type, acc, elem)
627- elseif op == :max
628- encode_MaxIOp! (cb, type, acc, elem; signedness)
629- else
630- error (" Unsupported integer reduction operation: $op " )
631- end
621+ op == :add ? encode_AddIOp! (cb, type, acc, elem) :
622+ op == :max ? encode_MaxIOp! (cb, type, acc, elem; signedness) :
623+ error (" Unsupported integer operation: $op " )
632624 end
633625end
634626
@@ -702,7 +694,72 @@ function emit_intrinsic!(ctx::CGCtx, ::typeof(Intrinsics.reshape), args)
702694 CGVal (current_val, result_type_id, Tile{elem_type, Tuple (target_shape)}, target_shape)
703695end
704696
705- # TODO : cuda_tile.scan
697+ # cuda_tile.scan
698+ @eval Intrinsics begin
699+ """
700+ scan(tile, axis_val, fn_type; reverse=false)
701+
702+ Parallel prefix scan along specified dimension.
703+ fn_type=:add for cumulative sum (only supported operation).
704+ reverse=false for forward scan, true for reverse scan.
705+ Compiled to cuda_tile.scan.
706+ """
707+ @noinline function scan (tile:: Tile{T, S} , :: Val{axis} , fn:: Symbol , reverse:: Bool = false ) where {T, S, axis}
708+ # Scan preserves shape - result has same dimensions as input
709+ Tile {T, S} ()
710+ end
711+ end
712+
713+ function emit_intrinsic! (ctx:: CGCtx , :: typeof (Intrinsics. scan), args)
714+ cb = ctx. cb
715+ tt = ctx. tt
716+
717+ # Get input tile
718+ input_tv = emit_value! (ctx, args[1 ])
719+ input_tv === nothing && error (" Cannot resolve input tile for scan" )
720+
721+ # Get scan axis
722+ axis = @something get_constant (ctx, args[2 ]) error (" Scan axis must be a compile-time constant" )
723+
724+ # Get scan function type (only :add is supported)
725+ fn_type = @something get_constant (ctx, args[3 ]) error (" Scan function type must be a compile-time constant" )
726+ fn_type == :add || error (" Only :add (cumulative sum) is currently supported for scan operations" )
727+
728+ # Get reverse flag (optional, defaults to false)
729+ reverse = false
730+ if length (args) >= 4
731+ reverse_val = get_constant (ctx, args[4 ])
732+ reverse = reverse_val === true
733+ end
734+
735+ # Get element type and shapes
736+ input_type = unwrap_type (input_tv. jltype)
737+ elem_type = input_type <: Tile ? input_type. parameters[1 ] : input_type
738+ input_shape = input_tv. shape
739+
740+ # For scan, output shape is same as input shape
741+ output_shape = copy (input_shape)
742+
743+ dtype = julia_to_tile_dtype! (tt, elem_type)
744+
745+ # Output tile type (same shape as input)
746+ output_tile_type = tile_type! (tt, dtype, output_shape)
747+
748+ # Scalar type for scan body (0D tile)
749+ scalar_tile_type = tile_type! (tt, dtype, Int[])
750+
751+ # Create identity value using operation_identity
752+ identity = operation_identity (Val (fn_type), dtype, elem_type)
753+
754+ # Emit ScanOp
755+ results = encode_ScanOp! (cb, [output_tile_type], [input_tv. v], axis, reverse, [identity], [scalar_tile_type]) do block_args
756+ acc, elem = block_args[1 ], block_args[2 ]
757+ res = encode_binop_body (cb, scalar_tile_type, acc, elem, fn_type, elem_type)
758+ encode_YieldOp! (cb, [res])
759+ end
760+
761+ CGVal (results[1 ], output_tile_type, Tile{elem_type, Tuple (output_shape)}, output_shape)
762+ end
706763
707764# cuda_tile.select
708765@eval Intrinsics begin
0 commit comments