<!-- mobian-agent-page publisher="dailydev" canonical="https://daily.dev/posts/switch-lowering-in-gcc-cg4bme6jx" -->

---
title: Switch Lowering in GCC | daily.dev
description: GCC lowers switch statements using three strategies: jump tables, bitset tests, and binary comparison trees. It picks a jump table when the ratio of table...
canonical: https://daily.dev/posts/switch-lowering-in-gcc-cg4bme6jx
twitter:card: summary_large_image
twitter:site: @dailydotdev
og:type: website
og:site_name: daily.dev
og:title: Switch Lowering in GCC | daily.dev
og:description: GCC lowers switch statements using three strategies: jump tables, bitset tests, and binary comparison trees. It picks a jump table when the ratio of table...
og:url: https://daily.dev/posts/switch-lowering-in-gcc-cg4bme6jx
og:image: https://api.daily.dev/og/posts/cG4BMe6jx.png
og:image:alt: Switch Lowering in GCC
og:image:width: 1200
og:image:height: 630
og:locale: en
---

> ## Documentation Index
> Fetch the complete documentation index at: https://daily.dev/llms.txt
> Use this file to discover all available pages before exploring further.

# Switch Lowering in GCC

**[Hacker News](https://daily.dev/sources/hn)** · 14 min read · 0 upvotes · 0 comments

## Summary

GCC lowers switch statements using three strategies: jump tables, bitset tests, and binary comparison trees. It picks a jump table when the ratio of table entries to comparisons stays under about 8 (when optimizing for speed) or 2 (when optimizing for size), with a minimum size threshold of case labels set by case_values_threshold, which defaults to 5 on modern x64 and Arm64. For non-contiguous small ranges, gcc can emit a single bit-test using the x86 'bt' instruction against a precomputed bitmask constant instead of branches. When neither jump table nor bitset is profitable, gcc falls back to a probability-weighted binary decision tree built from case label likelihoods. The post traces this logic through gcc's tree-switch-conversion.cc, including the dynamic programming used to choose optimal cluster splits.

## Full article

daily.dev links to this article rather than hosting it. Read it at the original source: <https://xoranth.net/gcc-switch>

## Questions this post answers

### What ratio does gcc use to decide whether to turn a switch statement into a jump table?

GCC compares the number of jump table entries to the number of comparisons needed, using a ratio of 8 when optimizing for speed (-O1, -O2, -O3, -Ofast) and a ratio of 2 when optimizing for size (-Os). If the jump table size divided by comparisons stays under that ratio, and the table has enough entries, gcc emits a jump table instead of a branch tree.

_Developers tuning hot switch statements can track compiler lowering heuristics like this on daily.dev._

### What is the minimum number of case labels gcc needs before it will generate a jump table on x86-64?

On modern x64 and Arm64, gcc's case_values_threshold function defaults to 5, meaning a jump table is only considered once there are at least that many case labels, since the indirect jump and bounds check carry overhead that isn't worth it for very small switches.

_Anyone benchmarking switch-case codegen can follow details like this threshold on daily.dev._

### How does gcc generate code for a switch statement with non-contiguous integer cases without using comparisons or a jump table?

GCC can emit a bit-test cluster: it computes a bitmask constant where each set bit corresponds to a valid case value offset from the minimum case label, then uses the x86 'bt' (bit test) instruction to check the carry flag for membership, avoiding both branching and a sparse jump table.

_Low-level developers debugging unexpected disassembly can look up patterns like bt-based switch lowering on daily.dev._

## Community take

How the wider developer community reacted, aggregated from 2 discussions and 35 comments across lobsters, hackernews (as of 2026-10-31).

**TL;DR:** Developers found the deep dive into GCC's switch-lowering internals interesting and dug into tangential technical details (missing optimizations, jump-table indirection, decision trees), while a side debate emerged about why neither GCC nor LLVM implement perfect hashing for large sparse switches.

**Sentiment:** 30% positive · 45% mixed · 25% skeptical

**The case for**

- Several commenters appreciated the cleverness of compiler optimization techniques described in the post.
- Concrete assembly-level tweaks (like dividing by 8 before the jump) were explored and benchmarked by commenters, showing real interest in the mechanics.
- One commenter noted a similar optimization for unicode regex ranges gave a real ~2x speedup in another context.

**The pushback**

- Commenters criticized GCC and LLVM for not implementing perfect hashing for large sparse switch tables despite it allegedly being a modest implementation effort.
- Some pushed back that perfect hashing is a niche optimization with limited real-world benefit since hot large sparse switches are rare.
- A tangent noted GCC can't safely do certain code-size-dependent optimizations (like jump-to-function instead of jump-to-jump) due to imprecise code size estimation.
- Unrelated complaints surfaced about long-standing unacknowledged LLVM bugs and large backlogs of open issues.

**By community**

- lobsters (mixed): Appreciation for compiler cleverness was tempered by skepticism, citing Proebsting's Law and mixed evidence on whether recompiling with modern compilers yields big speedups for old software.
- hackernews (heated): A substantive technical discussion about jump tables and decision trees coexisted with a contentious, sometimes personal argument over why perfect hashing isn't implemented in major compilers.

**Hottest debate:** Whether implementing perfect hashing for large sparse switch tables in GCC/LLVM is a valuable, low-effort improvement or a niche optimization not worth compiler maintainers' time.

**Open questions**

- Why was the LLVM perfect-hashing patch rejected a decade ago, and would it be reconsidered today?
- What are the actual performance implications of perfect hashing for switch tables compared to existing jump-table/decision-tree approaches?
- Why doesn't GCC optimize jump tables to call target functions directly instead of jumping through an intermediate jump?

**Highlights**

> What a shame for clang and gcc! They still don't implement perfect hashes for large sparse switch tables. I did that recently for my rcc C compiler, and it was just a single day of work. Esp. beneficial for unicode work. The LLVM patch was rejected a decade ago. Gcc has several unicode patches sitting in branches, which would also need that
> — [rurban on hackernews · 4 comments](https://news.ycombinator.com/item?id=50314612)

> Compiler optimizations are a trade-off between compile time, runtime, and code size, mediated by the availability of developer time. Perfect hashing for switch tables is useful mostly for large, sparse switches, but hot large, sparse switches are rare, and the closest examples I can think of (e.g., parse tables) are themselves likely generated from other tools, which could itself be changed in lieu of the compiler. It really doesn't come across as a useful optimization to try implementing in a compiler.
> — [jcranmer on hackernews · 1 comments](https://news.ycombinator.com/item?id=50317489)

> All the values are divisible by 8, so it could do it like this:     cmp  eax,40     ja   <return 0>     test eax,7     jnz  <return 0>     jmp  JumpTable[rax]
> — [rep\_lodsb on hackernews · 1 comments](https://news.ycombinator.com/item?id=50315051)

> Why the indirection? - why not have the jump table reference f0..fX directly rather than jumping to a jump?
> — [tsukikage on hackernews · 1 comments](https://news.ycombinator.com/item?id=50314741)

> If you believe https://proebsting.cs.arizona.edu/law.html the answer is no, at least depending on “old” and “huge”.
> — [lcapaldo on lobsters · 3 points, 2 comments](https://lobste.rs/s/ncclwy/switch_lowering_gcc#c_slilzc)

**Source threads**

- [lobsters](https://lobste.rs/s/ncclwy/switch_lowering_gcc) · 26 points · 4 comments
- [hackernews](https://news.ycombinator.com/item?id=50314085) · 166 points · 31 comments

## Similar posts on daily.dev

- [Branches in branch-free code](https://daily.dev/posts/branches-in-branch-free-code-trw8zoxp3) · Lobsters · 0 upvotes · 0 comments
- [Cracking a popcount benchmark](https://daily.dev/posts/cracking-a-popcount-benchmark-8ziaciwwj) · Planet Igalia · 0 upvotes · 0 comments
- [Lucky Code](https://daily.dev/posts/lucky-code-jwiwesdsx) · Hacker News · 0 upvotes · 0 comments
- [One Line x86 Change To GCC Compiler Nets \+12% Benchmark Win For Modern Intel/AMD CPUs](https://daily.dev/posts/one-line-x86-change-to-gcc-compiler-nets-12-benchmark-win-for-modern-intel-amd-cpus-hm9xklk3r) · Phoronix · 1 upvotes · 0 comments

---

Tags: [#c](https://daily.dev/tags/c), [#compiler-optimization](https://daily.dev/tags/compiler-optimization)

[View this post on daily.dev](https://daily.dev/posts/switch-lowering-in-gcc-cg4bme6jx)

```json
{"@context":"https://schema.org","@graph":[{"@type":"Organization","@id":"https://daily.dev/#organization","name":"daily.dev","url":"https://daily.dev","logo":{"@type":"ImageObject","url":"https://daily.dev/apple-touch-icon.png","width":180,"height":180},"sameAs":["https://twitter.com/dailydotdev","https://github.com/dailydotdev","https://www.linkedin.com/company/daily-dev-ltd"]},{"@type":"WebSite","@id":"https://daily.dev/#website","url":"https://daily.dev","name":"daily.dev","publisher":{"@id":"https://daily.dev/#organization"},"potentialAction":{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https://daily.dev/search?q={search_term_string}"},"query-input":"required name=search_term_string"}}]}
{"@context":"https://schema.org","@type":"TechArticle","headline":"Switch Lowering in GCC","url":"https://daily.dev/posts/switch-lowering-in-gcc-cg4bme6jx","mainEntityOfPage":{"@type":"WebPage","@id":"https://daily.dev/posts/switch-lowering-in-gcc-cg4bme6jx"},"datePublished":"2026-10-31T10:37:48.809Z","dateModified":"2026-10-31T18:24:01.638Z","description":"GCC lowers switch statements using three strategies: jump tables, bitset tests, and binary comparison trees. It picks a jump table when the ratio of table...","image":"https://media.daily.dev/image/upload/s--P4t4XyoV--/f_auto/v1722860399/public/Placeholder%2001","thumbnailUrl":"https://media.daily.dev/image/upload/s--P4t4XyoV--/f_auto/v1722860399/public/Placeholder%2001","isAccessibleForFree":true,"articleSection":"Hacker News","inLanguage":"en","publisher":{"@type":"Organization","name":"daily.dev","url":"https://daily.dev","logo":{"@type":"ImageObject","url":"https://daily.dev/apple-touch-icon.png","width":180,"height":180}},"author":{"@type":"Organization","name":"Hacker News","logo":"https://media.daily.dev/image/upload/t_logo,f_auto/v1/logos/hn","url":"https://daily.dev/sources/hn"},"commentCount":0,"discussionUrl":"https://daily.dev/posts/switch-lowering-in-gcc-cg4bme6jx","interactionStatistic":[{"@type":"InteractionCounter","interactionType":{"@type":"LikeAction"},"userInteractionCount":0},{"@type":"InteractionCounter","interactionType":{"@type":"CommentAction"},"userInteractionCount":0}],"keywords":"c,compiler-optimization","timeRequired":"PT14M"}
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https://daily.dev"},{"@type":"ListItem","position":2,"name":"Hacker News","item":"https://daily.dev/sources/hn"},{"@type":"ListItem","position":3,"name":"Switch Lowering in GCC"}]}
{"@context":"https://schema.org","@type":"FAQPage","@id":"https://daily.dev/posts/switch-lowering-in-gcc-cg4bme6jx#faq","mainEntity":[{"@type":"Question","name":"What ratio does gcc use to decide whether to turn a switch statement into a jump table?","acceptedAnswer":{"@type":"Answer","text":"GCC compares the number of jump table entries to the number of comparisons needed, using a ratio of 8 when optimizing for speed (-O1, -O2, -O3, -Ofast) and a ratio of 2 when optimizing for size (-Os). If the jump table size divided by comparisons stays under that ratio, and the table has enough entries, gcc emits a jump table instead of a branch tree. Developers tuning hot switch statements can track compiler lowering heuristics like this on daily.dev."}},{"@type":"Question","name":"What is the minimum number of case labels gcc needs before it will generate a jump table on x86-64?","acceptedAnswer":{"@type":"Answer","text":"On modern x64 and Arm64, gcc's case_values_threshold function defaults to 5, meaning a jump table is only considered once there are at least that many case labels, since the indirect jump and bounds check carry overhead that isn't worth it for very small switches. Anyone benchmarking switch-case codegen can follow details like this threshold on daily.dev."}},{"@type":"Question","name":"How does gcc generate code for a switch statement with non-contiguous integer cases without using comparisons or a jump table?","acceptedAnswer":{"@type":"Answer","text":"GCC can emit a bit-test cluster: it computes a bitmask constant where each set bit corresponds to a valid case value offset from the minimum case label, then uses the x86 'bt' (bit test) instruction to check the carry flag for membership, avoiding both branching and a sparse jump table. Low-level developers debugging unexpected disassembly can look up patterns like bt-based switch lowering on daily.dev."}}]}
```

