Skip to content

Commit f38e981

Browse files
jlebarclaude
andcommitted
x86: drop 7 S2 entries that aren't real bugs
Four pure sNaN-quieting losses (#112, #115, #116, #117) — known LLVM limitation, not worth filing in isolation. Three "poison → concrete value" folds (#123, #156, #247) — LangRef explicitly permits this: "It is correct to replace a poison value with an undef value or any value of the type." Removes the bug dirs, the 7 candidate files that map to them, and updates TRIAGE.md/README.md/workers/COVERAGE.md counts and refs. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
1 parent b4a46eb commit f38e981

31 files changed

Lines changed: 15 additions & 1304 deletions

File tree

‎x86/README.md‎

Lines changed: 2 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ Everything below here is machine-generated. Good luck.
1515

1616
Goal: find ≥100 real bugs in the x86 path through the default LLVM pass pipeline.
1717

18-
**Status: 152 reproducible bugs (well past the 100 goal). 253 total catalog entries (~100 are source-confirmed only). 484+ pending candidate notes in `candidates/` not yet promoted.**
18+
**Status: 145 reproducible bugs (well past the 100 goal). 246 total catalog entries (~100 are source-confirmed only). 484+ pending candidate notes in `candidates/` not yet promoted.**
1919

2020
Breakdown by repro kind:
2121
- crash (4): #071, #218, #222, #227
@@ -25,7 +25,7 @@ Breakdown by repro kind:
2525
- mir-diff (20): #124, #125, #196–#199, #208–#210, #213, #226, #231, #237, #238, #239, …
2626
- opt-diff (~110): all others
2727

28-
Most reproducible bugs fall in: metadata loss (`!nontemporal`, `!invariant.load`, `!alias.scope`, `!range`, FMF, `samesign`, syncscope, `!unpredictable`, `!prof`), poison/refinement violations (#136/187/188/194/195/206/207/233/236/247/248/251/252/253), and PGO corruptions (#215, #216, #232).
28+
Most reproducible bugs fall in: metadata loss (`!nontemporal`, `!invariant.load`, `!alias.scope`, `!range`, FMF, `samesign`, syncscope, `!unpredictable`, `!prof`), poison/refinement violations (#136/187/188/194/195/206/207/233/236/248/251/252/253), and PGO corruptions (#215, #216, #232).
2929

3030

3131
## Tools
@@ -158,18 +158,13 @@ Most reproducible bugs fall in: metadata loss (`!nontemporal`, `!invariant.load`
158158
| 109 | [109-memcpyopt-memsetmemcpy-drops-volatile-memset](bugs/109-memcpyopt-memsetmemcpy-drops-volatile-memset/) | MemCpyOpt processMemSetMemCpyDependence | volatile memset followed by memcpy: original deleted, replacement non-volatile (and equal-size case deletes outright) | confirmed (opt diff) |
159159
| 110 | [110-gisel-usube-inverted-borrow-sub128](bugs/110-gisel-usube-inverted-borrow-sub128/) | X86 GISel selectUAddSub (G_USUBE) | i128 sub: `setb; cmpb $1` inverts borrow → sbb adds 1 to high half | repro (runtime, GISel-only — `-global-isel` not default) |
160160
| 111 | [111-lower-atomic-drops-volatile-rmw-cmpxchg](bugs/111-lower-atomic-drops-volatile-rmw-cmpxchg/) | Transforms/Utils/LowerAtomic | `lower-atomic` lowers `atomicrmw volatile`/`cmpxchg volatile` into non-volatile load+store; volatile/ordering/syncscope dropped | repro (opt diff, pass not in default x86 pipeline) |
161-
| 112 | [112-fp-round-of-fp-extend-elides-snan-quieting](bugs/112-fp-round-of-fp-extend-elides-snan-quieting/) | DAGCombiner visitFP_ROUND | `(float)(double)x` round-trip folded to identity without FMF; IEEE-754 mandates sNaN→qNaN quieting on each convertFormat | confirmed (asm) |
162161
| 113 | [113-avx512-mask-arith-ss-sd-round-cur-direction-mxcsr](bugs/113-avx512-mask-arith-ss-sd-round-cur-direction-mxcsr/) | X86InstCombineIntrinsic | mask scalar `add/sub/mul/div.ss/sd.round` with rounding=4 (CUR_DIRECTION) folded to plain fadd, losing MXCSR-set rounding | confirmed (opt diff) |
163162
| 114 | [114-gvnsink-merges-volatile-stores](bugs/114-gvnsink-merges-volatile-stores/) | GVNSink ValueTable | volatile is included in expression hash; two equivalent volatile stores merged across branches into one sunk store | confirmed (opt diff) |
164-
| 115 | [115-simplifyfpbinop-snan-quieting-bypass-fmul](bugs/115-simplifyfpbinop-snan-quieting-bypass-fmul/) | SelectionDAG::simplifyFPBinop | `fmul X,1.0` / `fdiv X,1.0` fold to bare `retq` with no `nnan` check; sNaN bit-pattern + exception elided | confirmed (asm) |
165-
| 116 | [116-simplifyfpbinop-snan-quieting-bypass-fadd-neg0](bugs/116-simplifyfpbinop-snan-quieting-bypass-fadd-neg0/) | SelectionDAG::simplifyFPBinop | `fadd X,-0.0` / `fsub X,+0.0` likewise fold to `retq` (sister of #115) | confirmed (asm) |
166-
| 117 | [117-fdiv-neg1-snan-passthrough-via-xorps](bugs/117-fdiv-neg1-snan-passthrough-via-xorps/) | DAGCombiner visitFDIV→visitFMUL→visitFSUB | `fdiv X,-1.0` lowers to bare `xorps sign-mask` (no `divsd`); in-source FIXME at line 19057 | confirmed (asm) |
167163
| 118 | [118-sroa-drops-atomic-ordering](bugs/118-sroa-drops-atomic-ordering/) | Transforms/Scalar/SROA | predicate `if (LI.isVolatile()) NewLI->setAtomic(...)` should be `isAtomic()`; atomic seq_cst load/store reduced to plain access | confirmed (opt diff) |
168164
| 119 | [119-simplifycfg-merge-cond-stores-drops-atomic](bugs/119-simplifycfg-merge-cond-stores-drops-atomic/) | SimplifyCFG mergeConditionalStores | filters via `isUnordered()` (which accepts Unordered atomic) then emits plain `CreateStore`; atomic Unordered → plain store, racy access becomes UB | confirmed (opt diff) |
169165
| 120 | [120-simplifycfg-sink-merges-volatile-stores](bugs/120-simplifycfg-sink-merges-volatile-stores/) | SimplifyCFG SinkCommonCodeFromPredecessors | two volatile stores in mutually-exclusive branches sunk into one select+volatile-store; static count 2→1 violates LangRef volatile invariant | confirmed (opt diff) |
170166
| 121 | [121-simplifycfg-hoist-merges-volatile-loads](bugs/121-simplifycfg-hoist-merges-volatile-loads/) | SimplifyCFG hoistCommonCodeFromSuccessors | two volatile loads in mutually-exclusive branches hoisted to one unconditional volatile load | confirmed (opt diff) |
171167
| 122 | [122-simplifycfg-hoist-merges-seqcst-atomic-loads](bugs/122-simplifycfg-hoist-merges-seqcst-atomic-loads/) | SimplifyCFG hoistCommonCodeFromSuccessors | two `seq_cst` atomic loads in branches hoisted to one unconditional load; conditional→unconditional changes C++ S total order | confirmed (opt diff) |
172-
| 123 | [123-instcombine-constfold-nnan-ninf-returns-nan-inf-not-poison](bugs/123-instcombine-constfold-nnan-ninf-returns-nan-inf-not-poison/) | InstCombine ConstantFoldFPInstOperands | nnan/ninf FP op with NaN/Inf result folds to NaN/Inf constant instead of `poison` (LangRef: nnan+NaN result → poison) | confirmed (opt diff) |
173168
| 124 | [124-atomic-expand-load-to-cmpxchg-drops-volatile-syncscope](bugs/124-atomic-expand-load-to-cmpxchg-drops-volatile-syncscope/) | AtomicExpandPass expandAtomicLoadToCmpXchg | i128 atomic-volatile load with `singlethread` syncscope → cmpxchg without volatile + system-scope | confirmed (mir diff) |
174169
| 125 | [125-atomic-expand-store-to-xchg-drops-volatile-syncscope](bugs/125-atomic-expand-store-to-xchg-drops-volatile-syncscope/) | AtomicExpandPass expandAtomicStoreToXChg | i128 atomic-volatile store with `singlethread` → cmpxchg loop without volatile + system-scope; also inserts a bare non-volatile load of the dst | confirmed (mir diff) |
175170
| 126 | [126-licm-promote-drops-syncscope](bugs/126-licm-promote-drops-syncscope/) | LICM promoteLoopAccessesToScalars | preheader load and exit-block store dropped from `syncscope("singlethread")` to default System scope | confirmed (opt diff) |
@@ -202,7 +197,6 @@ Most reproducible bugs fall in: metadata loss (`!nontemporal`, `!invariant.load`
202197
| 153 | [153-dse-dominating-condition-drops-nontemporal](bugs/153-dse-dominating-condition-drops-nontemporal/) | DSE dominating-condition store merging | dropped `!nontemporal` on merged stores | confirmed (opt diff) |
203198
| 154 | [154-simplifycfg-sink-merges-two-volatile-seqcst-atomicrmw](bugs/154-simplifycfg-sink-merges-two-volatile-seqcst-atomicrmw/) | SimplifyCFG SinkCommonCodeFromPredecessors | volatile seq_cst `atomicrmw` instructions in mutually-exclusive branches sunk into one (sibling of #152) | confirmed (opt diff) |
204199
| 155 | [155-frexp-i64-libcall-stack-slot-overrun](bugs/155-frexp-i64-libcall-stack-slot-overrun/) | TargetLowering expandMultipleResultFPLibCall | `llvm.frexp.f64.i64` allocates 8-byte slot, libcall writes 4 (int), load reads 8 — uninitialized upper 4 bytes (info leak + wrong value) | confirmed (asm) |
205-
| 156 | [156-instcombine-fcmp-nnan-with-nan-folds-to-bool](bugs/156-instcombine-fcmp-nnan-with-nan-folds-to-bool/) | InstCombine fcmp w/ nnan + NaN constant | should be `poison` per LangRef nnan rules; instead folds to `true`/`false` | confirmed (opt diff) |
206200
| 157 | [157-dse-redundant-stores-of-existing-values-drops-nontemporal](bugs/157-dse-redundant-stores-of-existing-values-drops-nontemporal/) | DSE eliminateRedundantStoresOfExistingValues | `isIdenticalToWhenDefined` ignores metadata; merging two identical stores drops `!nontemporal` (different code path from #149/#153) | confirmed (opt diff) |
207201
| 158 | [158-sroa-memcpy-split-overrides-load-tbaa-nontemporal](bugs/158-sroa-memcpy-split-overrides-load-tbaa-nontemporal/) | SROA visitMemTransferInst split path | per-load `!tbaa`/`!nontemporal`/`!invariant.load` dropped + memcpy's broader TBAA substituted onto user loads | confirmed (opt diff) |
208202
| 159 | [159-sroa-phi-speculate-picks-aa-from-one-user](bugs/159-sroa-phi-speculate-picks-aa-from-one-user/) | SROA PHI speculation | AA tag picked from one user of the speculated PHI, applied to merged load — wrong for other users | confirmed (opt diff) |
@@ -293,7 +287,6 @@ Most reproducible bugs fall in: metadata loss (`!nontemporal`, `!invariant.load`
293287
| 244 | [244-scev-expander-drops-inrange-inbounds-on-gep](bugs/244-scev-expander-drops-inrange-inbounds-on-gep/) | SCEVExpander::expandAddToGEP | synthesized `%scevgep = getelementptr i8, ...` loses `inbounds` AND `inrange(-8, 24)` from source GEP | confirmed (opt diff) |
294288
| 245 | [245-instcombine-unpack-aggregate-drops-nontemporal-extra](bugs/245-instcombine-unpack-aggregate-drops-nontemporal-extra/) | InstCombine unpackStoreToAggregate | full enumeration of dropped kinds: `!nontemporal`, `!access_group`, `!invariant.group`, `!mem_parallel_loop_access`, `!DIAssignID` | confirmed (opt diff) |
295289
| 246 | [246-constantfolding-ldexp-i64-exponent-narrowed-to-int](bugs/246-constantfolding-ldexp-i64-exponent-narrowed-to-int/) | ConstantFolding.cpp:3715 ldexp i64 | `ldexp(1.0, i64 4294967330)` folded to `2^34` (i64→int narrowing wraps); expected `+inf` per LangRef | confirmed (opt diff) |
296-
| 247 | [247-constantfolding-bitcast-vector-poison-lane-folds-to-zero](bugs/247-constantfolding-bitcast-vector-poison-lane-folds-to-zero/) | ConstantFolding.cpp:79 foldConstVectorToAPInt | `bitcast <i16 0, i16 poison> to i32` treats poison lane as 0; downstream `icmp eq , 0` folds to `true` instead of poison | confirmed (opt diff) |
297290
| 248 | [248-instcombine-foldSelectIntoOp-ninf-mispropagated-to-new-select](bugs/248-instcombine-foldSelectIntoOp-ninf-mispropagated-to-new-select/) | InstCombineSelect.cpp:631 foldSelectIntoOp | `select c, fmul ninf(x,y), x` → `fmul (select ninf c, y, 1.0), x`; for `x=0,y=+inf,c=true` source returns NaN but new select returns +inf → poison | confirmed (opt diff) |
298291
| 249 | [249-function-attrs-ignores-operand-bundles](bugs/249-function-attrs-ignores-operand-bundles/) | FunctionAttrs.cpp:1903-1948 InstrBreaksNoFree/NoSync/NonThrowing | predicates use `CallBase::hasFnAttr` which ignores operand bundles; caller with `[ "side_effects"() ]` on leaf still infers `nofree nosync nounwind willreturn` | confirmed (opt diff) |
299292
| 250 | [250-simplifycfg-mergeConditionalStoreToAddress-drops-pstore-metadata](bugs/250-simplifycfg-mergeConditionalStoreToAddress-drops-pstore-metadata/) | SimplifyCFG.cpp:4409 mergeConditionalStoreToAddress | asymmetric combineMetadata + `SI->copyMetadata(*QStore)` drops PStore-only `!nontemporal`/`!tbaa`/...; `!invariant.group` special-case can taint merged store | confirmed (opt diff) |

‎x86/TRIAGE.md‎

Lines changed: 6 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
# Triage by Severity (upstream-impact focused)
22

3-
253 catalog entries. 152 reproducible at default x86 -O2. ~100 source-confirmed only. Tiers below assigned by user-visible impact when the bug fires. Within each tier the bugs are ordered by "report-first" priority.
3+
246 catalog entries. 145 reproducible at default x86 -O2. ~100 source-confirmed only. Tiers below assigned by user-visible impact when the bug fires. Within each tier the bugs are ordered by "report-first" priority.
4+
5+
(7 S2 entries previously listed have been removed: four pure sNaN-quieting losses (112, 115, 116, 117) — known LLVM limitation, not worth filing — and three "poison → concrete value" folds (123, 156, 247), which the LangRef explicitly permits: *"It is correct to replace a poison value with an undef value or any value of the type."*)
46

57
---
68

@@ -29,7 +31,7 @@ End-user observable wrong-value miscompiles. Highest non-crash severity.
2931
| **233** | ConstantFolding `llvm.fmuladd` folded as FMA, x86 lowers as `mulsd;addsd` | same IR yields `2^-104` (compile-time fold) vs `0.0` (runtime). Real value divergence visible by toggling constness. |
3032
| **003 / 110** | X86 GISel UADDE / USUBE inverted carry on multi-word add/sub | wrong upper word — only fires with `-global-isel` (NOT default on x86) |
3133

32-
## S2 — Alive2-falsifiable poison/refinement miscompiles (~22) — turns defined value into poison, or over-infers a flag that makes downstream code poison
34+
## S2 — Alive2-falsifiable poison/refinement miscompiles (~20) — turns defined value into poison, or over-infers a flag that makes downstream code poison
3335

3436
These are the strongest correctness-class non-runtime bugs. Several are already-known patterns getting independent confirmation; others are net-new.
3537

@@ -48,23 +50,11 @@ These are the strongest correctness-class non-runtime bugs. Several are already-
4850
| **234** | InstSimplify strict-FP `constrained.fadd nnan` fold | drops FE_INVALID exception side-effect (strict-FP semantics violated) |
4951
| **236** | InstCombineSimplifyDemanded `ashr exact → lshr exact` | for `%x=-1`, source returns 255; target returns poison (anti-refinement) |
5052
| **246** | ConstantFolding `ldexp.f64.i64(1.0, 4294967330)` | folds to `2^34` instead of `+inf`; sibling of #011 in const-fold rather than libcall expand |
51-
| **247** | ConstantFolding `bitcast <i16 0, i16 poison> to i32` | treats poison lane as 0 — downstream `icmp eq , 0` → `true` instead of `poison` |
5253
| **248** | InstCombine `foldSelectIntoOp` ninf mis-propagation | `select c, fmul ninf(x,y), x` → `fmul (select ninf c, y, 1.0), x`; for x=0,y=+inf,c=true source returns NaN, new select returns +inf → poison |
5354
| **251** | CVP undef-tainted lattice | `select i1 %cmp, i64 undef, i64 1` taints lattice → CVP adds `range(i64 1,3)` AND `add nuw nsw`; both unsound for undef=INT_MAX (matches upstream #114902) |
5455
| **252** | JumpThreading `unfoldSelectInstr` branches on poison | original uses `freeze`; after JT, freeze is gone and `br i1 %maybe_poison` → UB |
5556
| **253** | InstCombine `foldAddLikeCommutative` | `or disjoint (add nsw A,5), (B&250)` → `add nsw A, (or B,5)`; disjoint only proves no unsigned carry, not signed — for a=100,b=130 source returns -21, target → poison |
5657

57-
**Codegen sNaN-quieting losses (Alive2-falsifiable, IEEE-754 mandate):**
58-
59-
| # | Bug |
60-
|---|-----|
61-
| **112** | `(float)(double)x` folded to identity without `nnan`; IEEE-754 requires quieting on every convertFormat |
62-
| **115** | DAG `simplifyFPBinop` `fmul X,1.0`/`fdiv X,1.0` folded to bare `ret` with no `nnan` check |
63-
| **116** | Same for `fadd X,-0.0`/`fsub X,+0.0` |
64-
| **117** | `fdiv X,-1.0` → bare `xorps sign-mask` (no `divsd`); in-source FIXME |
65-
| **123** | InstCombine ConstantFoldFPInstOperands: `nnan`/`ninf` op with NaN/Inf result folds to NaN/Inf constant instead of `poison` per LangRef |
66-
| **156** | InstCombine `fcmp nnan` with NaN constant folds to `true`/`false` instead of `poison` |
67-
6858
**SeparateConstOffsetFromGEP, mem2reg, LICM (default O2 — UB-injection):**
6959

7060
| # | Bug |
@@ -165,7 +155,7 @@ Mostly missed-optimizations downstream: `!nontemporal`, `!tbaa`, `!range`, `!inv
165155
- `JumpThreading` only forwards MD_prof (#214, #260–#263, #670)
166156
- `SDAG memcpy/memmove/memset getMemcpyLoadsAndStores` series (#208–#210, #460–#462, #510)
167157

168-
(Full list: bugs #022, #023, #091, #103, #132, #133, #145, #146, #147, #149, #150, #153, #157, #163, #164, #165, #167, #168, #169, #170, #171, #172, #176, #177, #178, #179, #180, #183, #189, #196–#214, #228–#230, #237, #239, #241–#247, #250, #439, #460–#462, #485, #486, #489, …)
158+
(Full list: bugs #022, #023, #091, #103, #132, #133, #145, #146, #147, #149, #150, #153, #157, #163, #164, #165, #167, #168, #169, #170, #171, #172, #176, #177, #178, #179, #180, #183, #189, #196–#214, #228–#230, #237, #239, #241–#246, #250, #439, #460–#462, #485, #486, #489, …)
169159

170160
## S7 — Source-confirmed / latent (~100)
171161

@@ -189,11 +179,10 @@ Annotated with upstream-issue status as of 2026-05-21:
189179
| **206** | `fmod(NaN)` → poison via mis-named `IsNoNan` | No duplicate. **Novel.** | File |
190180
| **207** | `fdim(±Inf,±Inf)` → qNaN | No duplicate. **Novel.** | File |
191181
| **236** | ashr exact → lshr exact anti-refinement | No duplicate. **Novel** (in-tree test `ashr_can_be_lshr` bakes in the buggy output and needs updating with the fix) | File |
192-
| **247** | `bitcast <i16 0, i16 poison>` poison-lane→0 | No duplicate. **Novel.** | File |
193182
| **251** | CVP undef-tainted lattice | **Duplicate**: open issue [#114902](https://github.com/llvm/llvm-project/issues/114902), still open and unfixed | Comment on existing issue with our `add nuw nsw` additional case |
194183
| **240** | X86 stack-probe skips one-page alloca | No duplicate. **Novel** (security mitigation defeated under `-fstack-clash-protection`) | File |
195184
| **253** | InstCombine `foldAddLikeCommutative` over-infers nsw from `or disjoint` | No duplicate. **Novel.** | File |
196185

197-
**Net actionable**: 10 novel issues to file + 2 to comment on existing. The 2 duplicates (#071 #251) are both already known, so they don't need new issues — adding our reproducers as comments still has value.
186+
**Net actionable**: 9 novel issues to file + 2 to comment on existing. The 2 duplicates (#071 #251) are both already known, so they don't need new issues — adding our reproducers as comments still has value.
198187

199188
Then in S3 batch, the most upstream-friendly cluster is the **shared-helper class** of fixes — see `ROOT_CAUSE_PATCHES.md`: 7 PRs in ~225 lines of code close ~40 of the ~85 S6 metadata-loss bugs.

0 commit comments

Comments
 (0)