GCC Newspaper
OCTOBER 6, 2026
gcc — Proposed — Sentiment 8 / 10

RISCV: redundant return-only BB not eliminated

A factorial function compiled for RISCV produces an unnecessary return instruction, and the contributor seeks guidance on optimization passes.

The author reports an unnecessary return instruction generated for a RISC-V factorial function due to loop unrolling and fall-through. They investigated optimization passes like ‘bbro’ and ‘cleanup_cfg’ but couldn’t pinpoint the exact pass responsible for not eliminating the redundant basic block. The contributor, new to compiler development, added a custom fix and seeks advice on the correct approach.

In the Thread 2 participants
  1. Robert Guthrie <forkbombidable@gmail.com> proposer

    Reports a redundant return instruction in RISC-V compiled code and seeks guidance on compiler optimization passes.

    “The below basic recursive factorial function generates two `ret` insns when only one is necessary: the BB labeled with .L12 can be eliminated (by just re-targeting to .L1).”
  2. Jeff Law <jeffreyalaw@gmail.com> other

    Acknowledges the report and provides initial context.

    “On 8/30/26 1:34 PM, Robert Guthrie via Gcc wrote: > Hello, I have been exploring RISCV, compiling simple programs and > looking at the output. > The below basic recursive factorial function generates two `ret` insns > when only one is necessary: ...”

Technical Tradeoffs

  • The author's custom fix is overly specific and might not generalize.
  • Incorrectly modifying CFG passes like `try_optimize_cfg` can lead to infinite loops or break other optimizations.

In Details

The reporter observed that a simple recursive factorial function compiled for RISC-V generates two return instructions. This is caused by loop unrolling creating an early exit, and subsequent passes like 'bbro' arranging these returns such that one is redundant. The issue lies in the control flow graph (CFG) optimization passes failing to eliminate this redundant basic block, possibly due to conditions in cleanup_cfg or related functions.

For Context
RISC-V
An open-standard instruction set architecture (ISA) based on RISC principles, known for its modularity and extensibility.
return instruction
A machine code instruction that signals the end of a function's execution and transfers control back to the caller.
basic block (BB)
A sequence of instructions with a single entry point and a single exit point, typically used in compiler intermediate representations for optimization.
loop unrolling
An optimization technique where loop iterations are duplicated to reduce loop overhead and enable further optimizations.
fall-through
In control flow, when execution proceeds to the next instruction or basic block without an explicit jump or branch.
bbro
Likely refers to the 'Branch and Block Reordering' optimization pass in GCC, which aims to improve instruction cache performance.
cleanup_cfg
A function or pass within GCC's compiler infrastructure that cleans up and optimizes the Control Flow Graph (CFG) after other transformations.
CROSSJUMP
A specific optimization within GCC's CFG cleanup that identifies and merges basic blocks that are direct jumps to each other.
Filed Under: riscvoptimizationcompiler-internalscfg