[all-commits] [llvm/llvm-project] 17e2f3: [DAGCombiner] Refine an extload to a zextload unde...
Paweł Bylica via All-commits
all-commits at lists.llvm.org
Mon Sep 21 02:51:03 PDT 2026
Branch: refs/heads/users/chfast/dag-zext-trunc-extload
Home: https://github.com/llvm/llvm-project
Commit: 17e2f363a1db1eddf590c09fad2b7fc5370ead50
https://github.com/llvm/llvm-project/commit/17e2f363a1db1eddf590c09fad2b7fc5370ead50
Author: Paweł Bylica <pawel at hepcolgum.band>
Date: 2026-09-21 (Mon, 21 Sep 2026)
Changed paths:
M llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
A llvm/test/CodeGen/AArch64/zext-trunc-extload-dbg.ll
A llvm/test/CodeGen/AArch64/zext-trunc-extload.ll
Log Message:
-----------
[DAGCombiner] Refine an extload to a zextload under zext(trunc(...))
When a narrow load also has a user at its extended width, the load is
retyped into an any-extending load early and the remaining narrow use
becomes a truncate. A later zext of that truncate then has nothing to
fold against: the extload's high bits are undefined, so the mask cannot
be removed, and reduceLoadWidth refuses to narrow a load with several
users.
Refine the extload to a zextload in place instead. The truncate discards
only the load's extension bits, which are undefined, so defining them as
zero is valid for every existing user and it makes the zext a no-op. The
load keeps its value type and only its extension kind changes, unlike
tryToFoldExtOfExtload, which widens the load and therefore requires a
single use.
EXTLOAD is the only extension kind this applies to. A zextload already
has those bits known zero, so the known-bits (zext (truncate x)) fold
collapses that case before this one is reached, and a sextload has them
defined, so zeroing them would miscompile. Undefined bits are precisely
the case analysis cannot settle, because they become zero only by
performing the rewrite.
The legality condition matches tryToFoldExtOfExtload: a simple load can
be retyped before legalization without proving the result legal. Volatile
and atomic loads are not excluded, since the access itself is unchanged
and only the in-register extension differs, which is also how the
in-place retype in the (and (load), mask) fold treats them.
N is replaced before the load is retyped, as tryToFoldExtOfLoad and
tryToFoldExtOfExtload do. getExtLoad can return an existing zextload of
the same address, in which case replacing the load first CSEs the
truncate, and N along with it, into pre-existing nodes and deletes N.
The truncate's debug values are transferred to the replacement for the
same reason: it dies with N.
On AArch64 this turns "and x1, x0, #0xff" into "mov x1, x0". It also
fixes llvm/test/CodeGen/BPF/remove_truncate_9.ll under
-combiner-topological-sorting for -mcpu=v4, where the producer-first
worklist order reaches this shape on a target whose tests assert that no
zero-extension instruction is emitted.
The sign-extending analogue is deliberately not done: refining to a
SEXTLOAD forces users that want the raw narrow value to materialize a
copy, which costs an instruction on x86-64 with no measured win
elsewhere.
Assisted-by: Claude Code
To unsubscribe from these emails, change your notification settings at https://github.com/llvm/llvm-project/settings/notifications
More information about the All-commits
mailing list