Skip to content

Commit 2c1a1a7

Browse files
maleadtclaude
andauthored
Fix reduce identity encoding for floats and integers. (#186)
Float identities (e.g. -Inf for max, +Inf for min) were encoded as raw bit patterns via plain varint, but the bytecode format expects ap_int encoding (zigzag + varint). This caused the disassembler to show NaN instead of -Inf for maximum, and 1.5 instead of +Inf for minimum. Fix: use encode_signed_varint! with Int128-widened bits so the zigzag shift-left never overflows. Integer identities had a separate bug: they were zigzag-encoded, but the format stores them as raw values (no zigzag). The existing zigzag also had a UInt32 overflow on the shift-left for typemin(Int32). Fix: remove zigzag from integer identities entirely and widen to UInt128 for the varint encoder. Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent 7dd0238 commit 2c1a1a7

File tree

2 files changed

+75
-7
lines changed

2 files changed

+75
-7
lines changed

src/bytecode/writer.jl

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -339,9 +339,10 @@ function encode_tagged_float!(cb::CodeBuilder, identity::FloatIdentityVal)
339339
push!(cb.buf, 0x02)
340340
# Type ID
341341
encode_typeid!(cb.buf, identity.type_id)
342-
# Value as bits (using signed varint encoding for values <= 64 bits)
342+
# Value as ap_int: zigzag-encode the bit pattern, then varint.
343+
# Widen to Int128 so the shift-left never overflows.
343344
bits = float_to_bits(identity.value, identity.dtype)
344-
encode_varint!(cb.buf, bits)
345+
encode_signed_varint!(cb.buf, Int128(bits))
345346
end
346347

347348
"""
@@ -372,11 +373,9 @@ function mask_to_width(value::UInt128, ::Type{T}) where T <: Integer
372373
masked = value & mask
373374
U = unsigned(T)
374375
unsigned_masked = U(masked)
375-
if T <: Signed # do zig-zag encoding
376-
U((unsigned_masked << 1) (unsigned_masked >>> (bits - 1)))
377-
else
378-
unsigned_masked
379-
end
376+
# Integer identities are stored as raw values (no zigzag encoding).
377+
# Widen to UInt128 so the varint encoder handles any bit width.
378+
UInt128(unsigned_masked)
380379
end
381380

382381
"""

test/codegen/operations.jl

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -726,6 +726,75 @@ spec4d = ct.ArraySpec{4}(16, true)
726726
end
727727
end
728728

729+
# reduce identity values (zigzag-encoded in bytecode)
730+
@testset "identities" begin
731+
# Float32: sum → 0.0, maximum → -Inf (0xFF800000), minimum → +Inf (0x7F800000)
732+
@test @filecheck begin
733+
@check_label "entry"
734+
code_tiled(Tuple{ct.TileArray{Float32,2,spec2d}}) do a
735+
pid = ct.bid(1)
736+
tile = ct.load(a, pid, (4, 16))
737+
@check "identities=[0.000000e+00 : f32]"
738+
Base.donotdelete(sum(tile; dims=2))
739+
return
740+
end
741+
end
742+
@test @filecheck begin
743+
@check_label "entry"
744+
code_tiled(Tuple{ct.TileArray{Float32,2,spec2d}}) do a
745+
pid = ct.bid(1)
746+
tile = ct.load(a, pid, (4, 16))
747+
@check "identities=[0xFF800000 : f32]"
748+
Base.donotdelete(maximum(tile; dims=2))
749+
return
750+
end
751+
end
752+
@test @filecheck begin
753+
@check_label "entry"
754+
code_tiled(Tuple{ct.TileArray{Float32,2,spec2d}}) do a
755+
pid = ct.bid(1)
756+
tile = ct.load(a, pid, (4, 16))
757+
@check "identities=[0x7F800000 : f32]"
758+
Base.donotdelete(minimum(tile; dims=2))
759+
return
760+
end
761+
end
762+
763+
# Float16: maximum → -Inf (0xFC00), minimum → +Inf (0x7C00)
764+
@test @filecheck begin
765+
@check_label "entry"
766+
code_tiled(Tuple{ct.TileArray{Float16,2,spec2d}}) do a
767+
pid = ct.bid(1)
768+
tile = ct.load(a, pid, (4, 16))
769+
@check "identities=[0xFC00 : f16]"
770+
Base.donotdelete(maximum(tile; dims=2))
771+
return
772+
end
773+
end
774+
@test @filecheck begin
775+
@check_label "entry"
776+
code_tiled(Tuple{ct.TileArray{Float16,2,spec2d}}) do a
777+
pid = ct.bid(1)
778+
tile = ct.load(a, pid, (4, 16))
779+
@check "identities=[0x7C00 : f16]"
780+
Base.donotdelete(minimum(tile; dims=2))
781+
return
782+
end
783+
end
784+
785+
# Int32: maximum → typemin (zigzag of -2147483648)
786+
@test @filecheck begin
787+
@check_label "entry"
788+
code_tiled(Tuple{ct.TileArray{Int32,2,spec2d}}) do a
789+
pid = ct.bid(1)
790+
tile = ct.load(a, pid, (4, 16))
791+
@check "identities=[-2147483648"
792+
Base.donotdelete(maximum(tile; dims=2))
793+
return
794+
end
795+
end
796+
end
797+
729798
# argmax
730799
@test @filecheck begin
731800
@check_label "entry"

0 commit comments

Comments
 (0)