Skip to content

Commit 1e03fb3

Browse files
jlebarclaude
andcommitted
x86: +8 reproducible bugs (#174-181 atomic-expand metadata, instcombine bitcast/store, scalarize-masked-mem, separate-const-offset-from-gep)
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
1 parent a1f3e12 commit 1e03fb3

26 files changed

Lines changed: 2360 additions & 15 deletions

‎x86/README.md‎

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -197,3 +197,11 @@ Goal: find ≥100 real bugs in the x86 path through the default LLVM pass pipeli
197197
| 171 | [171-gvnhoist-range-md-union-expands-set](bugs/171-gvnhoist-range-md-union-expands-set/) | GVNHoist + getMostGenericRange | hoisted load `!range` is UNION of source ranges, claiming membership in extra range that neither original load had | confirmed (opt diff) |
198198
| 172 | [172-gvnhoist-store-nontemporal-silently-dropped](bugs/172-gvnhoist-store-nontemporal-silently-dropped/) | GVNHoist combineMetadata path | hoisted store drops `!nontemporal` (sibling of NewGVN store-expr bug) | confirmed (opt diff) |
199199
| 173 | [173-x86fold-NDDtoRMW-killsRegister-ignores-subreg](bugs/173-x86fold-NDDtoRMW-killsRegister-ignores-subreg/) | X86 NDD fold (foldMemoryOperandImpl) | `killsRegister` check doesn't account for sub-register kills; can fold over a still-live sub-reg | source-confirmed |
200+
| 174 | [174-atomic-expand-rmwcmpxchgloop-initload-drops-tbaa-noalias](bugs/174-atomic-expand-rmwcmpxchgloop-initload-drops-tbaa-noalias/) | AtomicExpandPass insertRMWCmpXchgLoop | InitLoaded missing `copyMetadataForAtomic`; cmpxchg has tbaa+noalias but seed load doesn't | confirmed (opt diff) |
201+
| 175 | [175-atomic-expand-expandPartwordCmpXchg-newCI-drops-tbaa](bugs/175-atomic-expand-expandPartwordCmpXchg-newCI-drops-tbaa/) | AtomicExpandPass expandPartwordCmpXchg | widened cmpxchg new CI missing `copyMetadataForAtomic`; sibling widenPartwordAtomicRMW does it correctly | confirmed (opt diff) |
202+
| 176 | [176-atomic-expand-convertAtomicLoadToIntegerType-drops-tbaa](bugs/176-atomic-expand-convertAtomicLoadToIntegerType-drops-tbaa/) | AtomicExpandPass convertAtomicLoadToIntegerType / convertAtomicStoreToIntegerType | drops `!tbaa`/`!noalias`/`!alias.scope`; sibling convertAtomicXchgToIntegerType does it correctly | confirmed (opt diff) |
203+
| 177 | [177-instcombine-store-bitcast-drops-invariant-group](bugs/177-instcombine-store-bitcast-drops-invariant-group/) | InstCombine combineStoreToNewValue switch | omits `MD_invariant_group`; `store (bitcast double X to i64) %p, !invariant.group` becomes plain store | confirmed (opt diff) |
204+
| 178 | [178-instcombine-store-bitcast-drops-noalias-addrspace](bugs/178-instcombine-store-bitcast-drops-noalias-addrspace/) | InstCombine combineStoreToNewValue switch | omits `MD_noalias_addrspace`; load/store asymmetric (copyMetadataForLoad has it) | confirmed (opt diff) |
205+
| 179 | [179-instcombine-load-of-select-drops-invariant-group-tbaa](bugs/179-instcombine-load-of-select-drops-invariant-group-tbaa/) | InstCombine load-of-select fold | broader than #165 — also strips `!invariant.group`, `!invariant.load`, `!tbaa`, `!nontemporal`, `!dereferenceable` | confirmed (opt diff) |
206+
| 180 | [180-scalarize-masked-mem-drops-metadata-const-mask](bugs/180-scalarize-masked-mem-drops-metadata-const-mask/) | ScalarizeMaskedMemIntrin constant-mask fast paths | drops `!range`/`!tbaa`/`!noalias`/`!nontemporal`/`!nonnull`/`!dereferenceable`; all-true path correctly copies metadata | confirmed (opt diff) |
207+
| 181 | [181-separate-const-offset-from-gep-false-inbounds](bugs/181-separate-const-offset-from-gep-false-inbounds/) | SeparateConstOffsetFromGEP swapGEPOperand | unconditionally `setIsInBounds(true)`; can mark a temporarily-OOB GEP as inbounds → guaranteed poison | confirmed (opt diff) |
Lines changed: 132 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,132 @@
1+
# w108: AtomicExpandPass insertRMWCmpXchgLoop InitLoaded drops !tbaa/!noalias/!alias.scope
2+
3+
## Root cause
4+
`AtomicExpandImpl::insertRMWCmpXchgLoop` (llvm/lib/CodeGen/AtomicExpandPass.cpp:1769)
5+
synthesizes an initial pre-loop load:
6+
7+
```
8+
LoadInst *InitLoaded = Builder.CreateAlignedLoad(ResultTy, Addr, AddrAlign);
9+
```
10+
11+
It then calls `InitLoaded->setVolatile(IsVolatile)` and conditionally
12+
`InitLoaded->setAtomic(Monotonic, SSID)`. The subsequent cmpxchg (created via
13+
the `CreateCmpXchg` callback) goes through `createCmpXchgInstFun` which
14+
explicitly calls `copyMetadataForAtomic(*Pair, *MetadataSrc)` at line 758 to
15+
carry `!tbaa`, `!alias.scope`, `!noalias`, `!noalias.addrspace`,
16+
`!access_group`, `!mmra` onto the cmpxchg.
17+
18+
The `InitLoaded` seed load does NOT receive any of that metadata. It only
19+
gets the metadata collected by `ReplacementIRBuilder` (which is just
20+
`!pcsections` and `!annotation`, see ctor at line 64).
21+
22+
The omission is invisible in a peephole reading of the file because the
23+
copy is on the cmpxchg, not the load. But the InitLoaded participates in the
24+
SAME memory location and aliasing semantics as the cmpxchg and the original
25+
atomicrmw.
26+
27+
## Trigger condition (x86)
28+
`X86TargetLowering::shouldExpandAtomicRMWInIR` returns `CmpXChg` for
29+
`Nand`, `Max`, `Min`, `UMax`, `UMin`, `FAdd`, `FSub`, `FMax`, `FMin`,
30+
`UIncWrap`, `UDecWrap`, `USubCond`, `USubSat` (see X86ISelLowering.cpp:32979-32995).
31+
These RMW ops always require a cmpxchg loop on x86, regardless of size.
32+
33+
Reproducer:
34+
35+
```
36+
target triple = "x86_64-unknown-linux-gnu"
37+
38+
define i32 @test_tbaa_nand(ptr %p) {
39+
%r = atomicrmw nand ptr %p, i32 1 seq_cst, align 4, !tbaa !2, !noalias !6
40+
ret i32 %r
41+
}
42+
43+
define i32 @test_tbaa_uincwrap(ptr %p) {
44+
%r = atomicrmw uinc_wrap ptr %p, i32 7 seq_cst, align 4, !tbaa !2, !noalias !6
45+
ret i32 %r
46+
}
47+
48+
!0 = !{!"alias-domain"}
49+
!1 = !{!"alias-scope-a", !0}
50+
!2 = !{!3, !3, i64 0}
51+
!3 = !{!"int", !4, i64 0}
52+
!4 = !{!"omnipotent char", !5, i64 0}
53+
!5 = !{!"Simple C/C++ TBAA"}
54+
!6 = !{!1}
55+
```
56+
57+
After `llc -mtriple=x86_64-unknown-linux-gnu -stop-after=atomic-expand`:
58+
59+
```
60+
define i32 @test_tbaa_nand(ptr %p) {
61+
%1 = load i32, ptr %p, align 4 ; <-- BUG: no !tbaa, no !noalias
62+
br label %atomicrmw.start
63+
atomicrmw.start:
64+
%loaded = phi i32 [ %1, %0 ], [ %newloaded, %atomicrmw.start ]
65+
%2 = and i32 %loaded, 1
66+
%new = xor i32 %2, -1
67+
%3 = cmpxchg ptr %p, i32 %loaded, i32 %new seq_cst seq_cst, align 4, !tbaa !0, !noalias !4
68+
%success = extractvalue { i32, i1 } %3, 1
69+
%newloaded = extractvalue { i32, i1 } %3, 0
70+
br i1 %success, label %atomicrmw.end, label %atomicrmw.start
71+
atomicrmw.end:
72+
ret i32 %newloaded
73+
}
74+
75+
define i32 @test_tbaa_uincwrap(ptr %p) {
76+
%1 = load i32, ptr %p, align 4 ; <-- BUG: no !tbaa, no !noalias
77+
br label %atomicrmw.start
78+
...
79+
}
80+
```
81+
82+
`%1` (the InitLoaded seed) lacks `!tbaa` and `!noalias` while the cmpxchg
83+
in the same loop carries both.
84+
85+
## Why this is a miscompile (not a quality issue)
86+
After AtomicExpand, the IR is handed back to the codegen pipeline and to the
87+
DAG combiner. The `!noalias` metadata on the cmpxchg promises the compiler
88+
that the cmpxchg's memory access does not alias the noalias-scope-tagged
89+
pointers in scope `!1`. But the SAME pointer `%p` is now accessed by an
90+
untagged load. A later pass that ingests the IR (e.g. a LICM/CSE under a
91+
PGSO/LTO recompile, or a manual `opt -tbaa -mldst-motion` run after this
92+
file is dumped) may:
93+
94+
1. CSE/merge the untagged `%1 = load i32, ptr %p` with a TBAA-tagged load of
95+
a different alias type at `ptr %p` (e.g. `load i32 ... !tbaa <other-type>`)
96+
that the original atomicrmw with TBAA `!tbaa !2` was explicitly distinct
97+
from. CSE looks for syntactic equality of the address; with no TBAA on the
98+
InitLoaded, the metadata-strip semantics of `MDNode::getMostGenericTBAA`
99+
make this load identical to any other untagged i32 load at `%p` even
100+
across alias domains.
101+
2. Use `BasicAA + TBAA` to conclude an aliasing store BEFORE the InitLoaded
102+
does NOT alias (because the cmpxchg with TBAA `!tbaa !2` says so), then
103+
sink the store past it; but for the InitLoaded the AA query collapses to
104+
plain BasicAA which DOES report MayAlias, producing inconsistent
105+
reorderings between the seed load and the cmpxchg in the loop. The two
106+
accesses to `%p` are now treated differently by aliasing analysis even
107+
though they are the SAME atomicrmw decomposition.
108+
3. With `!noalias !6`, an interloping load tagged `!alias.scope !6` MUST
109+
not be moved across the original RMW. After expansion the cmpxchg still
110+
forbids the move, but the InitLoaded does not, so the interloping load
111+
may now be sunk between the InitLoaded and the cmpxchg loop -- a
112+
semantic move that crosses the *original* RMW boundary.
113+
114+
This is the same class of metadata-loss miscompile as #088
115+
(`w88-rmwcmpxchgloop-initload-drops-md.md`) but for the more impactful
116+
TBAA/noalias/alias.scope metadata rather than `pcsections`.
117+
118+
## Fix
119+
At line 1769, after creating `InitLoaded`, call
120+
`copyMetadataForAtomic(*InitLoaded, *MetadataSrc)` (with the `MetadataSrc`
121+
argument that the function already receives at line 1740). The cmpxchg in
122+
the loop already does this at line 758; the seed load must too.
123+
124+
## Related bugs
125+
- #088 (`w88-rmwcmpxchgloop-initload-drops-md.md`): same call site, focuses
126+
on `!pcsections`; this entry covers the more dangerous AA metadata.
127+
- #066: convertAtomicLoadToIntegerType / expandAtomicLoadToCmpXchg drop
128+
syncscope/volatile -- sibling call sites in same file.
129+
- #024: widenPartwordAtomicRMW drops volatile.
130+
131+
The fix in #088 (if applied) does not necessarily cover this case because
132+
the metadata families are different switch arms in `copyMetadataForAtomic`.
Lines changed: 110 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,110 @@
1+
# w108: AtomicExpandPass expandPartwordCmpXchg widened cmpxchg drops !tbaa/!noalias/!pcsections
2+
3+
## Root cause
4+
`AtomicExpandImpl::expandPartwordCmpXchg` (llvm/lib/CodeGen/AtomicExpandPass.cpp:1247-1256)
5+
widens a sub-word `cmpxchg` to a word-sized one:
6+
7+
```
8+
AtomicCmpXchgInst *NewCI = Builder.CreateAtomicCmpXchg(
9+
PMV.AlignedAddr, FullWord_Cmp, FullWord_NewVal, PMV.AlignedAddrAlignment,
10+
CI->getSuccessOrdering(), CI->getFailureOrdering(), CI->getSyncScopeID());
11+
NewCI->setVolatile(CI->isVolatile());
12+
NewCI->setWeak(CI->isWeak());
13+
// BUG: no copyMetadataForAtomic(*NewCI, *CI)
14+
```
15+
16+
Contrast with the sibling helper at line 1141-1145, `widenPartwordAtomicRMW`,
17+
which explicitly does:
18+
19+
```
20+
AtomicRMWInst *NewAI = Builder.CreateAtomicRMW(
21+
Op, PMV.AlignedAddr, NewOperand, PMV.AlignedAddrAlignment,
22+
AI->getOrdering(), AI->getSyncScopeID());
23+
copyMetadataForAtomic(*NewAI, *AI); // <-- correctly preserves metadata
24+
```
25+
26+
The cmpxchg-widening path forgot the parallel call. The
27+
`ReplacementIRBuilder` constructor only auto-copies `!pcsections` and
28+
`!annotation`; the entire `copyMetadataForAtomic` family (tbaa, tbaa.struct,
29+
alias.scope, noalias, noalias.addrspace, access_group, mmra,
30+
amdgpu.no.remote.memory) is dropped.
31+
32+
Additionally, the pre-loop seed load `InitLoaded` at line 1221 has the same
33+
defect:
34+
35+
```
36+
LoadInst *InitLoaded = Builder.CreateLoad(PMV.WordType, PMV.AlignedAddr);
37+
```
38+
39+
No metadata copy at all. (Same bug as w108-insertRMWCmpXchgLoop, different
40+
call site.)
41+
42+
## Trigger condition
43+
`expandPartwordCmpXchg` runs when the cmpxchg value type is narrower than
44+
`TLI->getMinCmpXchgSizeInBits() / 8`. X86 does not override
45+
`getMinCmpXchgSizeInBits` so this path is not directly triggered on x86; it
46+
is the dominant path on AArch64/ARM/PPC for sub-word cmpxchg. However the
47+
function is in target-independent code and the bug applies to any of those
48+
backends.
49+
50+
For ARM-style reproducer (uses the same source file):
51+
52+
```
53+
target triple = "armv7-unknown-linux-gnueabi"
54+
55+
define {i8, i1} @test_partword_cmpxchg(ptr %p, i8 %cmp, i8 %new) {
56+
%r = cmpxchg ptr %p, i8 %cmp, i8 %new seq_cst seq_cst, align 1, !tbaa !2, !noalias !6
57+
ret {i8, i1} %r
58+
}
59+
60+
!0 = !{!"alias-domain"}
61+
!1 = !{!"alias-scope-a", !0}
62+
!2 = !{!3, !3, i64 0}
63+
!3 = !{!"int", !4, i64 0}
64+
!4 = !{!"omnipotent char", !5, i64 0}
65+
!5 = !{!"Simple C/C++ TBAA"}
66+
!6 = !{!1}
67+
```
68+
69+
After `llc -mtriple=armv7-unknown-linux-gnueabi -stop-after=atomic-expand`:
70+
71+
```
72+
define { i8, i1 } @test_partword_cmpxchg(ptr %p, i8 %cmp, i8 %new) {
73+
...
74+
%InitLoaded = load i32, ptr %AlignedAddr ; no !tbaa, no !noalias
75+
...
76+
%NewCI = cmpxchg ptr %AlignedAddr, i32 %FullWord_Cmp, i32 %FullWord_NewVal seq_cst seq_cst, align 4
77+
; ^^^ no !tbaa, no !noalias
78+
...
79+
}
80+
```
81+
82+
Both the seed load and the widened cmpxchg lose TBAA / noalias / pcsections,
83+
while the analogous `atomicrmw or` path through `widenPartwordAtomicRMW`
84+
correctly preserves them.
85+
86+
## Why this is a miscompile
87+
- The widened cmpxchg now reads/writes a word but the analysis pipeline no
88+
longer knows the TBAA tag of the originally-narrowed access. A subsequent
89+
TBAA-aware pass (e.g. LICM, MemCpyOpt, GVN under LTO recompile) may
90+
reorder a TBAA-distinct store past the widened cmpxchg.
91+
- The dropped `!noalias` permits a later pass to sink a noalias-protected
92+
load BETWEEN the InitLoaded seed and the widened cmpxchg -- crossing the
93+
original cmpxchg boundary that the noalias scope was protecting.
94+
- `!pcsections` dropped on the widened cmpxchg means the post-RTL pcsections
95+
emitter no longer records the patchable instruction at the right address.
96+
97+
## Fix
98+
1. Line 1250: insert `copyMetadataForAtomic(*NewCI, *CI);` after the
99+
`setWeak` call. Match `widenPartwordAtomicRMW` exactly.
100+
2. Line 1235 (after `setVolatile` on `InitLoaded`): insert
101+
`copyMetadataForAtomic(*InitLoaded, *CI);`.
102+
103+
## Related bugs
104+
- Sibling of `widenPartwordAtomicRMW` (line 1145) which gets this right.
105+
- #088 (`w88-rmwcmpxchgloop-initload-drops-md.md`): same family for the
106+
non-partword `insertRMWCmpXchgLoop`.
107+
- #024 (`w24-widenpartword-atomicrmw-drops-volatile.md`): predecessor
108+
metadata/volatile bug in same source file.
109+
- This entry is target-independent; reproducer chosen for ARM because
110+
X86 does not exercise `expandPartwordCmpXchg`.
Lines changed: 142 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,142 @@
1+
# w108: AtomicExpandPass convertAtomicLoadToIntegerType / convertAtomicStoreToIntegerType drop !tbaa, !noalias
2+
3+
## Root cause
4+
Two sibling helpers in `llvm/lib/CodeGen/AtomicExpandPass.cpp` cast a
5+
float/vector atomic load or store to an equivalent integer type so the
6+
backend can pattern-match it. Both correctly propagate volatile, ordering,
7+
and syncscope; neither calls `copyMetadataForAtomic`.
8+
9+
`convertAtomicLoadToIntegerType` (line 556-575):
10+
```
11+
auto *NewLI = Builder.CreateLoad(NewTy, Addr);
12+
NewLI->setAlignment(LI->getAlign());
13+
NewLI->setVolatile(LI->isVolatile());
14+
NewLI->setAtomic(LI->getOrdering(), LI->getSyncScopeID());
15+
// BUG: no copyMetadataForAtomic(*NewLI, *LI);
16+
```
17+
18+
`convertAtomicStoreToIntegerType` (line 697-712):
19+
```
20+
StoreInst *NewSI = Builder.CreateStore(NewVal, Addr);
21+
NewSI->setAlignment(SI->getAlign());
22+
NewSI->setVolatile(SI->isVolatile());
23+
NewSI->setAtomic(SI->getOrdering(), SI->getSyncScopeID());
24+
// BUG: no copyMetadataForAtomic(*NewSI, *SI);
25+
```
26+
27+
The sibling `convertAtomicXchgToIntegerType` at line 578-607 DOES call
28+
`copyMetadataForAtomic(*NewRMWI, *RMWI)` at line 598 -- so we have direct
29+
evidence from the same file that this metadata copy is the expected pattern.
30+
31+
## Trigger condition (x86, direct)
32+
`X86TargetLowering::shouldCastAtomicLoadInIR` returns `CastToInteger` for
33+
any floating-point or vector-of-floating-point atomic load
34+
(X86ISelLowering.cpp:33000-33004). The sibling `shouldCastAtomicStoreInIR`
35+
behaves analogously.
36+
37+
Reproducer:
38+
```
39+
target triple = "x86_64-unknown-linux-gnu"
40+
41+
define float @test_castload_tbaa(ptr %p) {
42+
%r = load atomic float, ptr %p seq_cst, align 4, !tbaa !2, !noalias !6
43+
ret float %r
44+
}
45+
46+
define float @test_castload_volatile(ptr %p) {
47+
%r = load atomic volatile float, ptr %p seq_cst, align 4, !tbaa !2, !noalias !6
48+
ret float %r
49+
}
50+
51+
define void @test_caststore_tbaa(ptr %p, float %v) {
52+
store atomic float %v, ptr %p seq_cst, align 4, !tbaa !2, !noalias !6
53+
ret void
54+
}
55+
56+
!0 = !{!"alias-domain"}
57+
!1 = !{!"alias-scope-a", !0}
58+
!2 = !{!3, !3, i64 0}
59+
!3 = !{!"int", !4, i64 0}
60+
!4 = !{!"omnipotent char", !5, i64 0}
61+
!5 = !{!"Simple C/C++ TBAA"}
62+
!6 = !{!1}
63+
```
64+
65+
After `llc -mtriple=x86_64-unknown-linux-gnu -stop-after=atomic-expand`:
66+
```
67+
define float @test_castload_tbaa(ptr %p) {
68+
%1 = load atomic i32, ptr %p seq_cst, align 4 ; <-- no !tbaa, no !noalias
69+
%2 = bitcast i32 %1 to float
70+
ret float %2
71+
}
72+
73+
define float @test_castload_volatile(ptr %p) {
74+
%1 = load atomic volatile i32, ptr %p seq_cst, align 4 ; <-- no !tbaa, no !noalias
75+
%2 = bitcast i32 %1 to float
76+
ret float %2
77+
}
78+
79+
define void @test_caststore_tbaa(ptr %p, float %v) {
80+
%1 = bitcast float %v to i32
81+
store atomic i32 %1, ptr %p seq_cst, align 4 ; <-- no !tbaa, no !noalias
82+
ret void
83+
}
84+
```
85+
86+
Original IR had `!tbaa !2` and `!noalias !6`; expanded IR has neither.
87+
88+
## Why this is a miscompile (vs. a quality issue)
89+
The expanded IR is then run through the rest of the codegen pipeline AND
90+
re-exposed to IR-level analyses (e.g. via `-passes='atomic-expand,gvn'`
91+
under the new pass manager, or LTO that re-invokes IR passes after target
92+
lowering hooks). Concretely:
93+
94+
1. The original `load atomic float, ptr %p ... !tbaa !2` carried a TBAA tag
95+
that ensured a TBAA-disjoint store of a different type at the same address
96+
could be moved past it. After dropping the tag, GVN/MemCpyOpt cannot prove
97+
the same disjointness, but conversely a *different* sibling load with
98+
`!tbaa !2` may now be CSE-merged with the untagged load because the
99+
untagged load is treated as "compatible with any TBAA tag" by
100+
`MDNode::getMostGenericTBAA`. The merged load result is then used for
101+
both, but it is only marked atomic with one set of metadata -- producing
102+
inconsistent aliasing decisions for the same SSA value.
103+
104+
2. The dropped `!noalias` permits a later AA-driven sink to move a load
105+
tagged `!alias.scope !6` past this atomic load. The original IR with
106+
`!noalias !6` on this atomic load promised that no `!alias.scope !6`
107+
access could be moved across it. The expanded IR makes no such promise.
108+
109+
3. The volatile reproducer (`test_castload_volatile`) preserves volatile
110+
(good) but still loses TBAA/noalias (bad). Volatile prevents elision,
111+
but does NOT prevent reordering of *non-volatile* accesses across the
112+
volatile load; only the metadata tags do.
113+
114+
## Fix
115+
Add `copyMetadataForAtomic(*NewLI, *LI);` after line 567 and
116+
`copyMetadataForAtomic(*NewSI, *SI);` after line 709. Match the sibling
117+
`convertAtomicXchgToIntegerType` at line 598.
118+
119+
## Also affected: expandAtomicLoadToCmpXchg
120+
The same TBAA/noalias drop happens in `expandAtomicLoadToCmpXchg` at line
121+
678. With `cx16` and i128 atomic load:
122+
```
123+
define i128 @test_load_cmpxchg_md(ptr %p) {
124+
%r = load atomic i128, ptr %p seq_cst, align 16, !tbaa !2, !noalias !6, !pcsections !7
125+
ret i128 %r
126+
}
127+
```
128+
becomes (after `llc -mattr=+cx16 -stop-after=atomic-expand`):
129+
```
130+
%1 = cmpxchg ptr %p, i128 0, i128 0 seq_cst seq_cst, align 16, !pcsections !0
131+
%loaded = extractvalue { i128, i1 } %1, 0, !pcsections !0
132+
```
133+
The pcsections survives only because `ReplacementIRBuilder` collects it;
134+
`!tbaa` and `!noalias` are silently dropped.
135+
136+
## Related bugs
137+
- Sibling of `convertAtomicXchgToIntegerType` (line 598) which gets it right.
138+
- #066: same call site, identified `volatile`/`syncscope` drop in
139+
expandAtomicLoadToCmpXchg. This entry covers the TBAA/noalias drop in two
140+
additional callers in the same file.
141+
- #088 (`w88-convertcmpxchgtoint-drops-md.md`): the sibling
142+
`convertCmpXChgToIntegerType` also has a similar pattern.

0 commit comments

Comments
 (0)