[ClangIR] Progress Report - August 2026

Follow-up to the July report. Numbers are from upstream main at 8074923be0f3 (2026-08-25) at -O2, x86_64 native on Linux. 2,177 commits since July, 73 of them touching clang/lib/CIR.

Numbers

All figures here have x86_64 calling-convention lowering (the ABI pass for the rest of this post) off, as in every report so far, so they compare directly with July.

Test Suite July Aug 17 Aug 25
SingleSource 97.1% (1794/1848) 97.8% (1808/1848) 97.5% (1802/1848)
MultiSource 94.0% (189/201) 94.5% (190/201) 93.5% (188/201)
SPEC CINT 2017 7/10 7/10 6/10
SPEC CFP 2017 5/8 7/8 5/8
libcxx (std/) 80.4% (7083/8814) 88.7% (7878/8880) 88.7% (7882/8891)
Self-hosting (per-TU) 96.6% (4490/4649) 99.87% (4674/4680) 99.3% (4668/4703)

Month over month that’s a good one: libcxx +8.3pp, self-hosting +2.7pp, SingleSource +8 tests.

The mid-August column is there because it shows what the last two weeks cost. SPEC CFP was at 7/8 on the 17th and is back to 5/8; SPEC CINT dropped to 6/10; MultiSource and self-hosting each gave a little back. Two regressions, below.

The ABI pass caught up

The ABI pass is enabled with -fclangir-call-conv-lowering. Upstream it was off by default until recently, and these reports have always measured with it off, it was too unfinished to measure through, since turning it on meant half of everything fell over on one unimplemented case.

New this month: both ways, on both dates.

Suite Aug 17 (off) Aug 17 (on) Aug 25 (off) Aug 25 (on)
SingleSource 1808/1848 1710/1848 1802/1848 1802/1848
MultiSource 190/201 182/201 188/201 191/201

On the 17th the pass still cost 98 SingleSource tests. On the 25th it costs nothing. SingleSource is identical either way, and MultiSource is better with it on.

September’s numbers will be measured with the ABI pass on. This is x86_64 only; on every other target it stays off until it catches up there too.

Two regressions

Both are single well-scoped defects rather than missing features, and each has a four-line reproducer in its issue.

Typed catch fails to verify at -O1+: 822 hits, the largest category this month. Cost three SPEC benchmarks: 523.xalancbmk_r (CINT 7→6), 511.povray_r and 526.blender_r (CFP 7→5). #219549.

[[no_unique_address]] on a struct wrapping an empty struct: 788 hits, and the whole self-hosting regression (31 of 35 failing targets, up from 2). LLVM’s own headers use the pattern. #219547.

One big fix

ExtVectorBoolType store/load is at zero. It was the #1 category in July (80 hits) and still #1 mid-August (82). Biggest thing ever cleared off this list, and a good part of why libcxx moved.

Self-hosting

Stage-2 bootstrap (a -fclangir-built clang recompiling LLVM/clang), per-TU, (still) ABI pass off.

July Aug 17 Aug 25
Targets built / total 4490 / 4649 4674 / 4680 4668 / 4703
Pass rate 96.6% 99.87% 99.3%

35 of 4,703 don’t build: 31 are the [[no_unique_address]] regression above, 4 hit the timeout (FuchsiaHandleChecker.cpp, llvm-dwarfutil.cpp, ObjcopyOptions.cpp, ELFDumper.cpp, same four as last time). The denominator moved because the tree grew.

Timeout here means over the 180 s per-TU budget, not that they never finish. Those four haven’t been looked at, but the one compile-time blowup I did characterise this month is an ABI-pass-off artefact: without sret, a large by-value aggregate return becomes an LLVM first-class aggregate, so one function picked up 20,000 insertvalue instructions and 43 minutes in the backend against 2 seconds without -fclangir (on SPEC CPU 2026). These four may be the same thing, in which case measuring with the ABI pass on makes them go away.

Top issues

Across libcxx, the test suites and self-hosting.

# Category Hits vs July
1 cir.try: handler must start with cir.begin_catch 174 NEW (regression)
2 [[no_unique_address]] empty-for-layout field 79 NEW (regression)
3 Coroutine builtins (coro_promise, _resume, _done, _destroy) 7 7 (was coro_id)
4 llvm::cast_if_present assertion (Casting.h) 6 NEW
5 llvm::cast assertion (Casting.h) 4 19
6 “pass manager failed to lower CIR to LLVMIR dialect” 4 13
7 “module verification error before running CIR passes” 4 NEW
8 AggExprEmitter: AtomicCast on a padded atomic 3 3
9 LowerVAARG assertion (MVT::f80) 3 2
10 declaration of kind: Import 2 2
11 AggExprEmitter: VisitCoawaitExpr 2 2

Gone to zero since July: ExtVectorBoolType store/load (35), which was the
month’s biggest single fix; “Lowering from LLVMIR dialect to llvm IR failed”
(14); and the X86 library-function NYI (2). __builtin_clear_padding is also at
zero — it was implemented upstream in #216126 on Aug 13.

CIR unit tests, as a sanity signal only: 983/1016 (936/957 mid-August, the suite grew by 59).

What’s next

  1. Fix the two regressions. Between them: three SPEC benchmarks and 29 extra self-host failures.
  2. Measure September with the ABI pass on. Worth saying plainly: the gap is confirmed closed on SingleSource and MultiSource, not on libcxx or self-hosting, so this could still move.
  3. Coroutines more than doubled (33 → 78) as coro_promise / coro_resume / coro_done. Biggest thing left that isn’t a regression.
  4. ValueTypes.cpp (34) and LowerVAARG (22) are one gap: CIR emits a generic va_arg, and neither an aggregate nor long double has an MVT the X86 backend can select. The aggregate half can’t be fixed in the backend at all.
  5. Compile time and memory are becoming their own problem, separate from correctness. Re-checking the four self-host timeouts with the ABI pass on is the cheap first step, they may simply be the missing-sret blowup.
  6. Still no ARM64 numbers; that sweep is pending.

Questions, corrections, contributions welcome.

11 Likes

Interesting!

I’m unfamiliar with the #1 cir.try issue, though I THINK @andykaylor mentioned something similar today?

I’m actually actively working #2 on the no_unique_address issue at the moment :smiley: It was an added assert, so we went from a miscompile to an assert.

#3 Coroutines are being worked on actively by @Andres-Salamanca :slight_smile:

#4: I BELIEVE I actually JUST fixed that this morning in [CIR] Fix materialize-temporary-expr for non scalar/aggregates by erichkeane · Pull Request #219514 · llvm/llvm-project · GitHub. EDIT: I misremembered here. This one ends up I THINK also being ABI related.

#5 (LowerVAARG) is one that we’re aware of, and is ABI related we believe.

#6: What issues for __builtin_clear_padding are you seeing? I commited an implementation for it on Aug 13: [CIR] Implement __builtin_clear_padding (#216126) · llvm/llvm-project@52e3ade · GitHub

All of the timeouts I analyzed while working through self-build (though I was getting different numbers!) were ABI related, so we’ll have to revisit that after ABI stuff is back in place.

4 Likes

Also, for #7 (the atomic cast one), IS that this NYI? Its the last one I see that it could be.

AggExprEmitter: AtomicCast not ignored and has padded atomic type

@amrdeveloper :smiley: ^^

1 Like

This NYI is interesting. With assert enabled, it will trigger ( [clang] Assertion `CGF.getContext().hasSameUnqualifiedType(E->getSubExpr()->getType(), E->getType()) && "Implicit cast types must be compatible"' failed. · Issue #115664 · llvm/llvm-project · GitHub ). I will check it and try to cover it in testing with a case that does not trigger assert until the issue is fixed in OGCG :smiley:

Good catch! Bug in my scripts, it had some leftovers from July, updated the post with corrected table.

Thanks everyone for the hard work, this is looking great!

Do you have the ability to produce some level of min repros/bug reports for these? They are unfortunately quite ‘generic’ and reproducing them based on this alone isn’t really possible.

What do you mean by not possible? All you gotta do is run the benchmarks in the report :slight_smile:

Reduced a few and added pointers for some of the others: top-issues.md · GitHub

1 Like

Cou

Could, don’t wanna :smiley:

Awesome, that’ll be great! I’ll look through some of those.

1 Like

Reduced a few and added pointers for some of the others: top-issues.md · GitHub

Thats great, the atomic cast snippet is very useful for me :smiley:

1 Like

Hi @bcardosolopes and everyone,

I noticed that Row 11 (AggExprEmitter: VisitCoawaitExpr) looks very straightforward.

Unless someone is already actively working on this, I would like to take this on and submit a patch. Please let me know if there are any caveats or ongoing work around this!

1 Like

@Andres-Salamanca has been doing a TON for coroutines support, you might ask him if he’s got that/for advice/etc.

+1 with @erichkeane

Also, I added a code snippet for reproducing it top-issues.md comments last week

1 Like