[llvm] [DAGCombiner] Allow tryToFoldExtOfLoad to use a sextload for zext nneg. (PR #81714)
Craig Topper via llvm-commits
llvm-commits at lists.llvm.org
Wed Feb 14 10:36:16 PST 2024
https://github.com/topperc updated https://github.com/llvm/llvm-project/pull/81714
>From 55eb482655e88d30121766b608ce3fadae6a2898 Mon Sep 17 00:00:00 2001
From: Craig Topper <craig.topper at sifive.com>
Date: Tue, 13 Feb 2024 22:34:14 -0800
Subject: [PATCH 1/5] [RISCV] Add test for an upcoming DAGCombine change. NFC
---
llvm/test/CodeGen/RISCV/load-setcc-combine.ll | 30 +++++++++++++++++++
1 file changed, 30 insertions(+)
create mode 100644 llvm/test/CodeGen/RISCV/load-setcc-combine.ll
diff --git a/llvm/test/CodeGen/RISCV/load-setcc-combine.ll b/llvm/test/CodeGen/RISCV/load-setcc-combine.ll
new file mode 100644
index 00000000000000..78e8925cf0d015
--- /dev/null
+++ b/llvm/test/CodeGen/RISCV/load-setcc-combine.ll
@@ -0,0 +1,30 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 4
+; RUN: llc < %s -mtriple=riscv64 | FileCheck %s
+
+define i8 @zext_nonneg_load_i16(ptr %x, ptr %y) {
+; CHECK-LABEL: zext_nonneg_load_i16:
+; CHECK: # %bb.0:
+; CHECK-NEXT: lh a0, 0(a0)
+; CHECK-NEXT: bltz a0, .LBB0_2
+; CHECK-NEXT: # %bb.1: # %cont
+; CHECK-NEXT: slli a0, a0, 48
+; CHECK-NEXT: srli a0, a0, 48
+; CHECK-NEXT: add a0, a1, a0
+; CHECK-NEXT: lbu a0, 0(a0)
+; CHECK-NEXT: ret
+; CHECK-NEXT: .LBB0_2: # %exit
+; CHECK-NEXT: li a0, 0
+; CHECK-NEXT: ret
+ %a = load i16, ptr %x
+ %b = icmp slt i16 %a, 0
+ br i1 %b, label %exit, label %cont
+
+cont:
+ %c = zext nneg i16 %a to i64
+ %d = getelementptr i8, ptr %y, i64 %c
+ %e = load i8, ptr %d
+ ret i8 %e
+
+exit:
+ ret i8 0
+}
>From 9a01897837fd28442fe1934628c3f356cf6ca0cc Mon Sep 17 00:00:00 2001
From: Craig Topper <craig.topper at sifive.com>
Date: Tue, 13 Feb 2024 23:20:24 -0800
Subject: [PATCH 2/5] [DAGCombiner] Allow tryToFoldExtOfLoad to use a sextload
for zext nneg.
If the load is used by any signed setccs, we can use a sextload
instead of zextload. Then we don't have to give up on extending
the load.
---
llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp | 31 ++++++++++++++-----
llvm/test/CodeGen/RISCV/load-setcc-combine.ll | 2 --
2 files changed, 23 insertions(+), 10 deletions(-)
diff --git a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
index 52011e593f2e0a..0df14896290279 100644
--- a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
@@ -12821,11 +12821,13 @@ static SDValue tryToFoldExtendOfConstant(SDNode *N, const SDLoc &DL,
// ExtendUsesToFormExtLoad - Trying to extend uses of a load to enable this:
// "fold ({s|z|a}ext (load x)) -> ({s|z|a}ext (truncate ({s|z|a}extload x)))"
// transformation. Returns true if extension are possible and the above
-// mentioned transformation is profitable.
+// mentioned transformation is profitable. If ChangeToSExt is non-null, it will
+// be set to true if a signed setcc is found. Caller should use a sextload.
static bool ExtendUsesToFormExtLoad(EVT VT, SDNode *N, SDValue N0,
unsigned ExtOpc,
SmallVectorImpl<SDNode *> &ExtendNodes,
- const TargetLowering &TLI) {
+ const TargetLowering &TLI,
+ bool *ChangeToSExt = nullptr) {
bool HasCopyToRegUses = false;
bool isTruncFree = TLI.isTruncateFree(VT, N0.getValueType());
for (SDNode::use_iterator UI = N0->use_begin(), UE = N0->use_end(); UI != UE;
@@ -12838,9 +12840,12 @@ static bool ExtendUsesToFormExtLoad(EVT VT, SDNode *N, SDValue N0,
// FIXME: Only extend SETCC N, N and SETCC N, c for now.
if (ExtOpc != ISD::ANY_EXTEND && User->getOpcode() == ISD::SETCC) {
ISD::CondCode CC = cast<CondCodeSDNode>(User->getOperand(2))->get();
- if (ExtOpc == ISD::ZERO_EXTEND && ISD::isSignedIntSetCC(CC))
+ if (ExtOpc == ISD::ZERO_EXTEND && ISD::isSignedIntSetCC(CC)) {
// Sign bits will be lost after a zext.
- return false;
+ if (!ChangeToSExt)
+ return false;
+ *ChangeToSExt = true;
+ }
bool Add = false;
for (unsigned i = 0; i != 2; ++i) {
SDValue UseOp = User->getOperand(i);
@@ -13154,12 +13159,14 @@ static SDValue tryToFoldExtOfExtload(SelectionDAG &DAG, DAGCombiner &Combiner,
// fold ([s|z]ext (load x)) -> ([s|z]ext (truncate ([s|z]extload x)))
// Only generate vector extloads when 1) they're legal, and 2) they are
-// deemed desirable by the target.
+// deemed desirable by the target. NonNegZExt can be set to true if a zero
+// extend has the nonneg flag to allow use of sextload if profitable.
static SDValue tryToFoldExtOfLoad(SelectionDAG &DAG, DAGCombiner &Combiner,
const TargetLowering &TLI, EVT VT,
bool LegalOperations, SDNode *N, SDValue N0,
ISD::LoadExtType ExtLoadType,
- ISD::NodeType ExtOpc) {
+ ISD::NodeType ExtOpc,
+ bool NonNegZExt = false) {
// TODO: isFixedLengthVector() should be removed and any negative effects on
// code generation being the result of that target's implementation of
// isVectorLoadExtDesirable().
@@ -13170,15 +13177,23 @@ static SDValue tryToFoldExtOfLoad(SelectionDAG &DAG, DAGCombiner &Combiner,
!TLI.isLoadExtLegal(ExtLoadType, VT, N0.getValueType())))
return {};
+ bool ChangeToSExt = false;
bool DoXform = true;
SmallVector<SDNode *, 4> SetCCs;
if (!N0.hasOneUse())
- DoXform = ExtendUsesToFormExtLoad(VT, N, N0, ExtOpc, SetCCs, TLI);
+ DoXform = ExtendUsesToFormExtLoad(VT, N, N0, ExtOpc, SetCCs, TLI,
+ NonNegZExt ? &ChangeToSExt : nullptr);
if (VT.isVector())
DoXform &= TLI.isVectorLoadExtDesirable(SDValue(N, 0));
if (!DoXform)
return {};
+ // Change extension type if we found a signed setcc.
+ if (ChangeToSExt) {
+ ExtOpc = ISD::SIGN_EXTEND;
+ ExtLoadType = ISD::SEXTLOAD;
+ }
+
LoadSDNode *LN0 = cast<LoadSDNode>(N0);
SDValue ExtLoad = DAG.getExtLoad(ExtLoadType, SDLoc(LN0), VT, LN0->getChain(),
LN0->getBasePtr(), N0.getValueType(),
@@ -13765,7 +13780,7 @@ SDValue DAGCombiner::visitZERO_EXTEND(SDNode *N) {
// Try to simplify (zext (load x)).
if (SDValue foldedExt =
tryToFoldExtOfLoad(DAG, *this, TLI, VT, LegalOperations, N, N0,
- ISD::ZEXTLOAD, ISD::ZERO_EXTEND))
+ ISD::ZEXTLOAD, ISD::ZERO_EXTEND, N->getFlags().hasNonNeg()))
return foldedExt;
if (SDValue foldedExt =
diff --git a/llvm/test/CodeGen/RISCV/load-setcc-combine.ll b/llvm/test/CodeGen/RISCV/load-setcc-combine.ll
index 78e8925cf0d015..403999b93126e2 100644
--- a/llvm/test/CodeGen/RISCV/load-setcc-combine.ll
+++ b/llvm/test/CodeGen/RISCV/load-setcc-combine.ll
@@ -7,8 +7,6 @@ define i8 @zext_nonneg_load_i16(ptr %x, ptr %y) {
; CHECK-NEXT: lh a0, 0(a0)
; CHECK-NEXT: bltz a0, .LBB0_2
; CHECK-NEXT: # %bb.1: # %cont
-; CHECK-NEXT: slli a0, a0, 48
-; CHECK-NEXT: srli a0, a0, 48
; CHECK-NEXT: add a0, a1, a0
; CHECK-NEXT: lbu a0, 0(a0)
; CHECK-NEXT: ret
>From 902093a84e72660d8c9f49f4f627aa15ddd52f68 Mon Sep 17 00:00:00 2001
From: Craig Topper <craig.topper at sifive.com>
Date: Tue, 13 Feb 2024 23:33:32 -0800
Subject: [PATCH 3/5] fixup! clang-format
---
llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
index 0df14896290279..e8995b781a7f96 100644
--- a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
@@ -13778,9 +13778,9 @@ SDValue DAGCombiner::visitZERO_EXTEND(SDNode *N) {
}
// Try to simplify (zext (load x)).
- if (SDValue foldedExt =
- tryToFoldExtOfLoad(DAG, *this, TLI, VT, LegalOperations, N, N0,
- ISD::ZEXTLOAD, ISD::ZERO_EXTEND, N->getFlags().hasNonNeg()))
+ if (SDValue foldedExt = tryToFoldExtOfLoad(
+ DAG, *this, TLI, VT, LegalOperations, N, N0, ISD::ZEXTLOAD,
+ ISD::ZERO_EXTEND, N->getFlags().hasNonNeg()))
return foldedExt;
if (SDValue foldedExt =
>From ba0115fbcc66676b3d3a9f95b71c7fc8e746185b Mon Sep 17 00:00:00 2001
From: Craig Topper <craig.topper at sifive.com>
Date: Wed, 14 Feb 2024 10:13:29 -0800
Subject: [PATCH 4/5] !fixup Detect signed setccs early to change the load
extend type before the call to isLoadExtLegal.
---
llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp | 53 +++++++++++--------
1 file changed, 30 insertions(+), 23 deletions(-)
diff --git a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
index e8995b781a7f96..4b45e1d9e24409 100644
--- a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
@@ -12821,13 +12821,11 @@ static SDValue tryToFoldExtendOfConstant(SDNode *N, const SDLoc &DL,
// ExtendUsesToFormExtLoad - Trying to extend uses of a load to enable this:
// "fold ({s|z|a}ext (load x)) -> ({s|z|a}ext (truncate ({s|z|a}extload x)))"
// transformation. Returns true if extension are possible and the above
-// mentioned transformation is profitable. If ChangeToSExt is non-null, it will
-// be set to true if a signed setcc is found. Caller should use a sextload.
+// mentioned transformation is profitable.
static bool ExtendUsesToFormExtLoad(EVT VT, SDNode *N, SDValue N0,
unsigned ExtOpc,
SmallVectorImpl<SDNode *> &ExtendNodes,
- const TargetLowering &TLI,
- bool *ChangeToSExt = nullptr) {
+ const TargetLowering &TLI) {
bool HasCopyToRegUses = false;
bool isTruncFree = TLI.isTruncateFree(VT, N0.getValueType());
for (SDNode::use_iterator UI = N0->use_begin(), UE = N0->use_end(); UI != UE;
@@ -12840,12 +12838,9 @@ static bool ExtendUsesToFormExtLoad(EVT VT, SDNode *N, SDValue N0,
// FIXME: Only extend SETCC N, N and SETCC N, c for now.
if (ExtOpc != ISD::ANY_EXTEND && User->getOpcode() == ISD::SETCC) {
ISD::CondCode CC = cast<CondCodeSDNode>(User->getOperand(2))->get();
- if (ExtOpc == ISD::ZERO_EXTEND && ISD::isSignedIntSetCC(CC)) {
+ if (ExtOpc == ISD::ZERO_EXTEND && ISD::isSignedIntSetCC(CC))
// Sign bits will be lost after a zext.
- if (!ChangeToSExt)
- return false;
- *ChangeToSExt = true;
- }
+ return false;
bool Add = false;
for (unsigned i = 0; i != 2; ++i) {
SDValue UseOp = User->getOperand(i);
@@ -13167,33 +13162,45 @@ static SDValue tryToFoldExtOfLoad(SelectionDAG &DAG, DAGCombiner &Combiner,
ISD::LoadExtType ExtLoadType,
ISD::NodeType ExtOpc,
bool NonNegZExt = false) {
+ if (!ISD::isNON_EXTLoad(N0.getNode()) ||
+ !ISD::isUNINDEXEDLoad(N0.getNode()))
+ return {};
+
+ // If this is zext nneg, see if it would make sense to treat it as a sext.
+ if (NonNegZExt) {
+ assert(ExtLoadType == ISD::ZEXTLOAD && ExtOpc == ISD::ZERO_EXTEND &&
+ "Unexpected load type or opcode");
+ for (SDNode::use_iterator UI = N0->use_begin(), UE = N0->use_end(); UI != UE;
+ ++UI) {
+ SDNode *User = *UI;
+ if (User->getOpcode() == ISD::SETCC) {
+ ISD::CondCode CC = cast<CondCodeSDNode>(User->getOperand(2))->get();
+ if (ISD::isSignedIntSetCC(CC)) {
+ ExtLoadType = ISD::SEXTLOAD;
+ ExtOpc = ISD::SIGN_EXTEND;
+ break;
+ }
+ }
+ }
+ }
+
// TODO: isFixedLengthVector() should be removed and any negative effects on
// code generation being the result of that target's implementation of
// isVectorLoadExtDesirable().
- if (!ISD::isNON_EXTLoad(N0.getNode()) ||
- !ISD::isUNINDEXEDLoad(N0.getNode()) ||
- ((LegalOperations || VT.isFixedLengthVector() ||
- !cast<LoadSDNode>(N0)->isSimple()) &&
- !TLI.isLoadExtLegal(ExtLoadType, VT, N0.getValueType())))
+ if ((LegalOperations || VT.isFixedLengthVector() ||
+ !cast<LoadSDNode>(N0)->isSimple()) &&
+ !TLI.isLoadExtLegal(ExtLoadType, VT, N0.getValueType()))
return {};
- bool ChangeToSExt = false;
bool DoXform = true;
SmallVector<SDNode *, 4> SetCCs;
if (!N0.hasOneUse())
- DoXform = ExtendUsesToFormExtLoad(VT, N, N0, ExtOpc, SetCCs, TLI,
- NonNegZExt ? &ChangeToSExt : nullptr);
+ DoXform = ExtendUsesToFormExtLoad(VT, N, N0, ExtOpc, SetCCs, TLI);
if (VT.isVector())
DoXform &= TLI.isVectorLoadExtDesirable(SDValue(N, 0));
if (!DoXform)
return {};
- // Change extension type if we found a signed setcc.
- if (ChangeToSExt) {
- ExtOpc = ISD::SIGN_EXTEND;
- ExtLoadType = ISD::SEXTLOAD;
- }
-
LoadSDNode *LN0 = cast<LoadSDNode>(N0);
SDValue ExtLoad = DAG.getExtLoad(ExtLoadType, SDLoc(LN0), VT, LN0->getChain(),
LN0->getBasePtr(), N0.getValueType(),
>From 2bb7c866f4d09f28d07dbe1b04c21c28fb5c52dc Mon Sep 17 00:00:00 2001
From: Craig Topper <craig.topper at sifive.com>
Date: Wed, 14 Feb 2024 10:35:52 -0800
Subject: [PATCH 5/5] fixup! clang-format
---
llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp | 7 +++----
1 file changed, 3 insertions(+), 4 deletions(-)
diff --git a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
index 4b45e1d9e24409..bfd4c48387ef1d 100644
--- a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
@@ -13162,16 +13162,15 @@ static SDValue tryToFoldExtOfLoad(SelectionDAG &DAG, DAGCombiner &Combiner,
ISD::LoadExtType ExtLoadType,
ISD::NodeType ExtOpc,
bool NonNegZExt = false) {
- if (!ISD::isNON_EXTLoad(N0.getNode()) ||
- !ISD::isUNINDEXEDLoad(N0.getNode()))
+ if (!ISD::isNON_EXTLoad(N0.getNode()) || !ISD::isUNINDEXEDLoad(N0.getNode()))
return {};
// If this is zext nneg, see if it would make sense to treat it as a sext.
if (NonNegZExt) {
assert(ExtLoadType == ISD::ZEXTLOAD && ExtOpc == ISD::ZERO_EXTEND &&
"Unexpected load type or opcode");
- for (SDNode::use_iterator UI = N0->use_begin(), UE = N0->use_end(); UI != UE;
- ++UI) {
+ for (SDNode::use_iterator UI = N0->use_begin(), UE = N0->use_end();
+ UI != UE; ++UI) {
SDNode *User = *UI;
if (User->getOpcode() == ISD::SETCC) {
ISD::CondCode CC = cast<CondCodeSDNode>(User->getOperand(2))->get();
More information about the llvm-commits
mailing list