{
  "id": 14170630,
  "title": "Chasing a -O2 pessimization in antcc",
  "url": "https://urgent.news/2026/10/13/chasing-a-o2-pessimization-in-antcc",
  "topic": "tech",
  "section": "Tech",
  "published": "2026-10-13T09:33:50.000Z",
  "source": {
    "name": "Lobsters",
    "slug": "lobsters",
    "url": "https://386s.org/w/lua-antcc-pessimization/"
  },
  "original_language": "en",
  "account": "Recently, the writer was benchmarking the code efficiency of their C compiler, antcc, and discovered that the optimized builds were slower than expected. The writer's compiler doesn't implement many optimizations, so a significant slowdown shouldn't occur. The writer suspected that the inlining heuristics might be too aggressive, causing the code size to increase and leading to poor instruction cache performance. Disabling inlining seemed to resolve the issue.\n\nThe writer further investigated the function luaV_execute, which became ~43KB with -O2, more than double the size of the -O1 build. This function is the main bytecode interpreter loop for the Lua VM, making it a challenging one for a compiler to work with. The writer tried tweaking the inlining thresholds, but it didn't help; either few things got inlined, or small functions started getting inlined, causing the slowdown.\n\nExamining the Intermediate Representation (IR) showed that after all optimizations, the -O2 IR was only 11% bigger than the -O1 IR. However, the binary size difference was a staggering 2.4x. The writer then focused on the instruction selection and register allocation passes, as they were responsible for mapping virtual temporaries to physical registers. instruction selection only expanded into small sequences of instructions, so it couldn't be the cause.\n\nThe register allocation process involves mapping virtual temporaries to physical registers, but with limited registers, some variables have to go on the stack, known as spilling. When there aren't enough registers for all temporaries, register pressure occurs, causing a lot of instructions to be created to shuffle values between stack and registers. In this case, 40% of instructions in luaV_execute were just stack⇄register movs, resulting in a +70% blowup after regalloc. The writer concluded that the 16 phi instructions, being live across the whole loop, were causing a lot of register pressure, leading to the significant code size blowup from stack spilling.",
  "summary": null,
  "key_points": [],
  "editors_take": null,
  "illustration": null,
  "coverage": {
    "outlets": 1,
    "also_reported_by": []
  },
  "ai_generated": true,
  "disclaimer": "Summaries, key points and the editor’s take are written by software from other outlets’ reporting and may contain errors — always check the linked original."
}