Skip to content

Commit 0cfdb3e

Browse files
author
Patrick Häcker
committed
Align performance tests with PackedStructs.jl
1 parent 19e0daa commit 0cfdb3e

1 file changed

Lines changed: 8 additions & 9 deletions

File tree

test/runtests.jl

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -529,11 +529,15 @@ end
529529
# Performance invariants
530530
# ============================================================================
531531

532-
# Capture LLVM IR of `f(::types...)` and return the lines containing actual operations: drop preamble (`define`/`declare`), labels, braces, comments, blank lines, and the trailing `ret` (which is bookkeeping, not an operation — when the caller inlines `f`, only the operation lines remain).
532+
# Capture LLVM IR of `f(::types...)` and return the lines containing actual operations: drop preamble (`define`/`declare`), labels, braces, comments, blank lines, the trailing `ret` (bookkeeping, not an operation — when the caller inlines `f`, only the operation lines remain), and `--code-coverage` counter increments (`atomicrmw add` into a fixed pointer) so the count is the same with or without coverage instrumentation.
533533
function llvm_ops(f, types)
534534
io = IOBuffer()
535535
InteractiveUtils.code_llvm(io, f, types; debuginfo=:none, raw=false)
536-
filter(!contains(r"^\s*($|;|define|declare|\}|\{\s*$|.+:\s*$|ret\b)"), split(io |> take! |> String, "\n"))
536+
lines = split(io |> take! |> String, "\n")
537+
filter(lines) do l
538+
!contains(l, r"^\s*($|;|define|declare|\}|\{\s*$|.+:\s*$|ret\b)") &&
539+
!contains(l, "atomicrmw add ptr inttoptr")
540+
end
537541
end
538542

539543
# A `call` instruction targeting an LLVM intrinsic (`@llvm.ctpop`, `@llvm.abs`, …) is a single native instruction, not a runtime dispatch. Only flag calls into Julia runtime functions (`@j_*`, `@julia_*`, `@ijl_*`, `@jl_*`).
@@ -546,7 +550,7 @@ runtime_calls(ops) = count(l -> occursin("call ", l) && !occursin("@llvm.", l),
546550
# `>>>` with a runtime shift amount lowers to ~13 IR lines (mask, branch, mod), but the typical hot-path use is a constant shift; wrap it in a helper so the constant folds into the body.
547551
shr1(x::UInt3) = x >>> 1
548552

549-
# `(label, f, types, exact_ops)`. Counts are exact on Julia 1.11+ with default codegen options (calibrated on 1.11.9 and 1.13.0-rc1; both produce identical IR for these methods). Coverage instrumentation and `--check-bounds=yes` both inflate counts (CI runs with both), and 1.10's codegen differs, so the exact-count check is gated below.
553+
# `(label, f, types, exact_ops)`. Counts are exact on Julia 1.11+ (calibrated on 1.11.9 and 1.13.0-rc1; both produce identical IR for these methods); 1.10's codegen differs, so the exact-count check is gated to 1.11+ below.
550554
cases = [
551555
("UInt3 +", Base.:+, Tuple{UInt3, UInt3}, 2),
552556
("UInt3 *", Base.:*, Tuple{UInt3, UInt3}, 2),
@@ -564,17 +568,12 @@ runtime_calls(ops) = count(l -> occursin("call ", l) && !occursin("@llvm.", l),
564568
("UInt20 +", Base.:+, Tuple{UInt20, UInt20}, 2),
565569
]
566570

567-
# Exact counts only hold for clean codegen: Julia 1.11+, no coverage instrumentation, and `--check-bounds` at its default (0 = default, 1 = yes, 2 = no). The `runtime_calls == 0` invariant remains the important one and runs unconditionally.
568-
counts_calibrated = VERSION >= v"1.11" &&
569-
Base.JLOptions().code_coverage == 0 &&
570-
Base.JLOptions().check_bounds == 0
571-
572571
for (label, f, types, exact_ops) in cases
573572
ops = llvm_ops(f, types)
574573
# No dispatch into runtime helpers — every operation must lower to native instructions or LLVM intrinsics. Also rules out allocations, which would surface as `@jl_gc_*` calls.
575574
@test runtime_calls(ops) == 0
576575
# Exact op count — any drift (up or down) signals a codegen change worth a look.
577-
counts_calibrated && @test length(ops) == exact_ops
576+
VERSION >= v"1.11" && @test length(ops) == exact_ops
578577
end
579578
end
580579

0 commit comments

Comments
 (0)