[llvm] [DAGCombiner] Look through freeze for ext(freeze(extload(x))) (PR #178669)
David Sherwood via llvm-commits
llvm-commits at lists.llvm.org
Thu Jan 29 07:01:00 PST 2026
https://github.com/david-arm created https://github.com/llvm/llvm-project/pull/178669
This patch fixes a regression introduced by PR #175022, where
a freeze was introduced with the following transformation:
ext(freeze(load(x))) -> freeze(extload(x))
If a new extend is introduced afterwards we then have
ext(freeze(extload(x)))
which doesn't get picked up by existing DAG combines due to
the freeze getting in the way.
>From 9938fe8fed7bf937093c7bb62567d2492b443f6e Mon Sep 17 00:00:00 2001
From: David Sherwood <david.sherwood at arm.com>
Date: Thu, 29 Jan 2026 14:57:57 +0000
Subject: [PATCH 1/2] [NFC] Refactor tryToFoldExtOfExtload
---
llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp | 33 ++++++++++---------
1 file changed, 18 insertions(+), 15 deletions(-)
diff --git a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
index 93cc67ae00f4b..8281578a1b095 100644
--- a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
@@ -14592,27 +14592,30 @@ static SDValue tryToFoldExtOfExtload(SelectionDAG &DAG, DAGCombiner &Combiner,
const TargetLowering &TLI, EVT VT,
bool LegalOperations, SDNode *N,
SDValue N0, ISD::LoadExtType ExtLoadType) {
- SDNode *N0Node = N0.getNode();
- bool isAExtLoad = (ExtLoadType == ISD::SEXTLOAD) ? ISD::isSEXTLoad(N0Node)
- : ISD::isZEXTLoad(N0Node);
- if ((!isAExtLoad && !ISD::isEXTLoad(N0Node)) ||
- !ISD::isUNINDEXEDLoad(N0Node) || !N0.hasOneUse())
+ auto OldExtLoad = dyn_cast<LoadSDNode>(N0.getNode());
+ if (!OldExtLoad)
return SDValue();
- LoadSDNode *LN0 = cast<LoadSDNode>(N0);
- EVT MemVT = LN0->getMemoryVT();
- if ((LegalOperations || !LN0->isSimple() ||
- VT.isVector()) &&
+ bool isAExtLoad = (ExtLoadType == ISD::SEXTLOAD)
+ ? ISD::isSEXTLoad(OldExtLoad)
+ : ISD::isZEXTLoad(OldExtLoad);
+ if ((!isAExtLoad && !ISD::isEXTLoad(OldExtLoad)) ||
+ !ISD::isUNINDEXEDLoad(OldExtLoad) || !N0.hasOneUse())
+ return SDValue();
+
+ EVT MemVT = OldExtLoad->getMemoryVT();
+ if ((LegalOperations || !OldExtLoad->isSimple() || VT.isVector()) &&
!TLI.isLoadExtLegal(ExtLoadType, VT, MemVT))
return SDValue();
- SDValue ExtLoad =
- DAG.getExtLoad(ExtLoadType, SDLoc(LN0), VT, LN0->getChain(),
- LN0->getBasePtr(), MemVT, LN0->getMemOperand());
+ SDLoc DL(OldExtLoad);
+ SDValue ExtLoad = DAG.getExtLoad(ExtLoadType, DL, VT, OldExtLoad->getChain(),
+ OldExtLoad->getBasePtr(), MemVT,
+ OldExtLoad->getMemOperand());
Combiner.CombineTo(N, ExtLoad);
- DAG.ReplaceAllUsesOfValueWith(SDValue(LN0, 1), ExtLoad.getValue(1));
- if (LN0->use_empty())
- Combiner.recursivelyDeleteUnusedNodes(LN0);
+ DAG.ReplaceAllUsesOfValueWith(SDValue(OldExtLoad, 1), ExtLoad.getValue(1));
+ if (OldExtLoad->use_empty())
+ Combiner.recursivelyDeleteUnusedNodes(OldExtLoad);
return SDValue(N, 0); // Return N so it doesn't get rechecked!
}
>From b333f80490aaa8e4e7f02440f0b9e74a14bd82ad Mon Sep 17 00:00:00 2001
From: David Sherwood <david.sherwood at arm.com>
Date: Thu, 29 Jan 2026 14:58:18 +0000
Subject: [PATCH 2/2] [DAGCombiner] Look through freeze for
ext(freeze(extload(x)))
This patch fixes a regression introduced by PR #175022, where
a freeze was introduced with the following transformation:
ext(freeze(load(x))) -> freeze(extload(x))
If a new extend is introduced afterwards we then have
ext(freeze(extload(x)))
which doesn't get picked up by existing DAG combines due to
the freeze getting in the way.
---
llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp | 20 ++++++++++++++-----
llvm/test/CodeGen/X86/known-bits.ll | 4 +---
2 files changed, 16 insertions(+), 8 deletions(-)
diff --git a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
index 8281578a1b095..cb00a1acc4bca 100644
--- a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
@@ -14592,7 +14592,9 @@ static SDValue tryToFoldExtOfExtload(SelectionDAG &DAG, DAGCombiner &Combiner,
const TargetLowering &TLI, EVT VT,
bool LegalOperations, SDNode *N,
SDValue N0, ISD::LoadExtType ExtLoadType) {
- auto OldExtLoad = dyn_cast<LoadSDNode>(N0.getNode());
+ bool Frozen = N0.getOpcode() == ISD::FREEZE;
+ auto OldExtLoad =
+ dyn_cast<LoadSDNode>(Frozen ? N0.getOperand(0).getNode() : N0.getNode());
if (!OldExtLoad)
return SDValue();
@@ -14600,7 +14602,7 @@ static SDValue tryToFoldExtOfExtload(SelectionDAG &DAG, DAGCombiner &Combiner,
? ISD::isSEXTLoad(OldExtLoad)
: ISD::isZEXTLoad(OldExtLoad);
if ((!isAExtLoad && !ISD::isEXTLoad(OldExtLoad)) ||
- !ISD::isUNINDEXEDLoad(OldExtLoad) || !N0.hasOneUse())
+ !ISD::isUNINDEXEDLoad(OldExtLoad) || !OldExtLoad->hasNUsesOfValue(1, 0))
return SDValue();
EVT MemVT = OldExtLoad->getMemoryVT();
@@ -14612,10 +14614,18 @@ static SDValue tryToFoldExtOfExtload(SelectionDAG &DAG, DAGCombiner &Combiner,
SDValue ExtLoad = DAG.getExtLoad(ExtLoadType, DL, VT, OldExtLoad->getChain(),
OldExtLoad->getBasePtr(), MemVT,
OldExtLoad->getMemOperand());
- Combiner.CombineTo(N, ExtLoad);
+ SDValue Res = ExtLoad;
+ if (Frozen) {
+ Res = DAG.getFreeze(ExtLoad);
+ Res = DAG.getNode(
+ ExtLoadType == ISD::SEXTLOAD ? ISD::AssertSext : ISD::AssertZext, DL,
+ Res.getValueType(), Res,
+ DAG.getValueType(OldExtLoad->getValueType(0).getScalarType()));
+ }
+ Combiner.CombineTo(N, Res);
DAG.ReplaceAllUsesOfValueWith(SDValue(OldExtLoad, 1), ExtLoad.getValue(1));
- if (OldExtLoad->use_empty())
- Combiner.recursivelyDeleteUnusedNodes(OldExtLoad);
+ if (N0->use_empty())
+ Combiner.recursivelyDeleteUnusedNodes(N0.getNode());
return SDValue(N, 0); // Return N so it doesn't get rechecked!
}
diff --git a/llvm/test/CodeGen/X86/known-bits.ll b/llvm/test/CodeGen/X86/known-bits.ll
index dbcc8eceeb037..58a0595e4322a 100644
--- a/llvm/test/CodeGen/X86/known-bits.ll
+++ b/llvm/test/CodeGen/X86/known-bits.ll
@@ -7,8 +7,7 @@ define void @knownbits_zext_in_reg(ptr) nounwind {
; X86: # %bb.0: # %BB
; X86-NEXT: pushl %ebx
; X86-NEXT: movl {{[0-9]+}}(%esp), %eax
-; X86-NEXT: movzbl (%eax), %eax
-; X86-NEXT: movzwl %ax, %ecx
+; X86-NEXT: movzbl (%eax), %ecx
; X86-NEXT: imull $101, %ecx, %eax
; X86-NEXT: shrl $14, %eax
; X86-NEXT: imull $177, %ecx, %edx
@@ -32,7 +31,6 @@ define void @knownbits_zext_in_reg(ptr) nounwind {
; X64-LABEL: knownbits_zext_in_reg:
; X64: # %bb.0: # %BB
; X64-NEXT: movzbl (%rdi), %eax
-; X64-NEXT: movzwl %ax, %eax
; X64-NEXT: imull $101, %eax, %ecx
; X64-NEXT: shrl $14, %ecx
; X64-NEXT: imull $177, %eax, %edx
More information about the llvm-commits
mailing list