cl: preserve nil checks for unused dereferences - #2316
Conversation
There was a problem hiding this comment.
Review summary
This is a clean, well-motivated correctness fix. Consolidating the len(refs) == 0 unused-dereference handling into a single unconditional path (evaluate the pointer, record the panic location, assertNilDerefBase, AssertNilDeref) is a strict superset of the removed large-non-pointer and slice-to-array branches, and it also closes the previously-uncovered plain *p gap where an unused load could be eliminated by LLVM without emitting the required Go nil panic. The skipUnusedArrayDeref (range-over-array) exception is correctly preserved, the removed t.RawType() != nil guard was safe to drop (the checks operate on the pointer operand v.X, not on v's result type), the new block returns correctly, and the golden/xfail updates are consistent with loads now being elided in favor of explicit nil checks. Regression coverage is added at both the IR level (TestUnusedDerefEmitsNilGuard) and runtime level (TestUnusedNilDerefOperationsPanic).
Two minor, non-blocking observations are left inline. No safety, performance, or correctness regressions were found.
Codecov Report✅ All modified and coverable lines are covered by tests. 📢 Thoughts on this report? Let us know! |
LLGo baseline benchmarks
Program measurements
Core language and compiler benchmarks
Compared with |
6e5d94c to
dd4eb50
Compare
dd4eb50 to
aaf2809
Compare
Summary
fixedbugs/issue38496.goImplementation
When a Go SSA dereference has no non-debug referrers, LLGo no longer emits an unused load and relies on LLVM to retain it. It evaluates the pointer expression, records the panic location, checks any dereference base, and emits
AssertNilDerefdirectly.The existing range-over-array exception remains unchanged because that synthetic unused dereference does not represent a source-level dereference that must panic.
This PR intentionally does not implement the broader explicit nil-check strategy required by derived-address and large-offset cases in
nilptr2.goandnilptr.go. Those cases are classified separately by #2313. It also contains no nil-check liveness optimization, receiver analysis, or CI change.Golden changes
Only two existing LLVM snapshots change:
_testdata/varinit: remove an unused global scalar load_testrt/cvar: remove two unused aggregate C-variable loadsNo additional golden updates are required on the latest
main.Validation
go test ./cl -run '^TestUnusedDerefEmitsNilGuard$' -count=1go test ./cl -run '^TestRunAndTestFromTestdata$/^varinit$' -count=1go test ./cl -run '^TestRunAndTestFromTestrt$/^cvar$' -count=1LLGO_BUILD_CACHE=off llgo test -run '^TestUnusedNilDerefOperationsPanic$' ./test/gofixedbugs/issue38496.gopassed on Darwin/arm64 with Go 1.26.5cl/compile.gostatement block is hit, including the builtin-referenced effectful-array pathgit diff --check