llvm / llvm/llvm-project

[AArch64][SelectionDAG] scalar_to_vector(anyextload i8) not matched by ExtLoad8_16AllModes patterns — root gap behind the neon-dotreduce regression in #217185 (workaround in place)

Open
#224,181 1 comment 0 reactions 0 assignees View on GitHub
backend:AArch64 llvm:SelectionDAG
Dominant language
LLVM
Stars
40.5k
Forks
18.7k
PR merge metrics
PR metrics pending

Description

Background
PR #217185 fixes ISD::SCALAR_TO_VECTOR upper-element poison semantics. During its development a codegen regression surfaced in llvm/test/CodeGen/AArch64/neon-dotreduce.ll: the lane-32 i8 load degraded from a direct ldr b (FPR) to ldrb w8 + fmov s1, w8 (GPR→FPR move). Per review feedback (@RKSimon), this is tracked separately rather than folded into #217383 (verified unrelated — no aext(freeze(load)) shape involved).

Root-cause chain (from instrumented-build analysis in #217185)
1. With corrected PoisonOnly queries, the build_vector → AND/OR-mask fold in DAGCombiner now (correctly) freezes its source vector: getFreeze(CurVec, InsertedEltMask, PoisonOnly) can no longer elide the freeze because masked-off lanes trace back to the SCALAR_TO_VECTOR poison lanes.
2. visitFREEZE pushes the freeze down through the zext/extract chain, RAUW'ing users of the stv to freeze(stv(extload i8)).
3. SimplifyDemandedVectorElts' freeze(stv(x)) → stv(freeze(x)) fold (DemandedElts == 1) sinks the freeze below SCALAR_TO_VECTOR → stv(freeze(extload)). freeze(load) can never be dropped (a load is only poison-free with !noundef), and AArch64 ExtLoad8_16AllModes patterns only cover zextload/extload — so ISel stops matching.

Workaround currently in #217185 (note per review request)
TargetLowering::SimplifyDemandedVectorElts skips the freeze-through-stv sink when the scalar operand is a load: freeze(stv(load)) is equivalent for demanded element 0 and keeps the load visible to ISel patterns. This restores ldr b and removed the test diff, but it is a targeted workaround, not a root fix.

Remaining gaps / follow-up directions
- Add anyextload variants to ExtLoad8_16AllModes (safe: LDRBui/LDURBi zero-extend, which satisfies anyext semantics), and/or
- Add a combine forming an ext/zextload for scalar_to_vector(load) when only element 0 is demanded.

Once either lands, the SimplifyDemandedVectorElts workaround can be revisited/removed.

Related: #217185 (context + workaround), #155270 (separate: bfloat.ll PR92471 ZERO_EXTEND_VECTOR_INREG handling), #217383 (confirmed unrelated).

Contributor guide

Open the contributing guide

Research direction

Start with llvm/test/CodeGen/AArch64/neon-dotreduce.ll and trace the ExtLoad8_16AllModes patterns and SimplifyDemandedVectorElts entry point described in the issue. Determine whether adding anyextload coverage or forming an ext/zextload for scalar_to_vector(load) resolves the regression, then verify that the test selects direct ldr b codegen and that the existing workaround can be revisited.

Written by the indexing model from the issue text.

Assessment

Domain
compilers
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Active
Clarity
Mostly clear
Newbie friendliness
48/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.